面向对象编程是最有效的软件编写方法之一
在面向对象编程时,你编写表示现实世界中的事物和情景的类,并基于这些类来创建对象。
根据类来创建对象称为实例化,这让你能够使用类的实例
创建和使用类
创建Dog类
class Dog: """一次模拟小狗的简单尝试""" def __init__(self, name, age): """初始化属性 name 和 age""" self.name = name self.age = age def sit(self): """模拟小狗收到命令时坐下""" print(f"{self.name} is now sitting.") def roll_over(self): print(f"{self.name} rolled over!")
在Python中,首字母大写的名称指的是类,因为这是我们创建的全新的类,所以定义时不加括号,然后是一个文档字符串,对这个类的功能做了描述
__init__() 方法
类中的函数称为方法,前面学到的有关函数的一切都适用于方法,就目前而言,唯一重要的差别是调用方法的方式。
__init__()是一个特殊方法,每当你根据Dog类创建新实例时,Python都会自动运行它,在这个方法的名称中,前后各有两个下划线,这是一种约定,是为了避免Python默认方法与普通方法发生名称冲突。
我们将__init__()方法定义成包括三个形参:self、name、age。在这个方法的定义当中,self必不可少,而且必须位于其他形参的前面,因为当Python调用这个方法来创建Dog实例时,将自然传入实参self,该实参是一个指向实例本身的引用,让实例能够访问类中的属性和方法,当我们根据Dog类创建实例时,都只需给最后两个形参(name和age提供值)。
在__init__()方法内定义的两个变量都有前缀self,以self为前缀的变量可供类中的所有方法使用,可以通过类的任意实例来访问,self.name=name获取与形参name相关联的值,并将其赋给变量name,然后该变量被关联到当前创建的实例。
self.age = age的作用与此类似,想这样可通过实例访问的变量称为属性。
Dog类还定义了另外两个方法:sit()和roll_over()。由于这些方法的执行不需要额外的信息,因此只有一个形参self.
根据类创建实例:
class Dog: """一次模拟小狗的简单尝试""" def __init__(self, name, age): """初始化属性 name 和 age""" self.name = name self.age = age def sit(self): """模拟小狗收到命令时坐下""" print(f"{self.name} is now sitting.") def roll_over(self): print(f"{self.name} rolled over!") my_dog = Dog('rich', 8) print(f"My dog's name is {my_dog.name}") print(f"My dog is {my_dog.age} years old")
访问属性:
my_dog.name
调用方法
my_dog = Dog('rich', 8) my_dog.sit() my_dog.roll_over()
练习9.1:
class Restaurant: def __init__(self,restaurant_name,cuisine_type): self.restaurant_name = restaurant_name self.cuisine_type = cuisine_type def describe_restaurant(self): print(f"restaurant's name is {self.restaurant_name}") print(f"cuisine_type is {self.cuisine_type}") def open_restaurant(self): print(f"{self.restaurant_name.title()} is opening") restaurant = Restaurant('dongbei BBQ', 'dun') restaurant.describe_restaurant() restaurant.open_restaurant()
练习9.3
class User: def __init__(self, first_name, last_name, age, phone_number): self.first_name = first_name self.last_name = last_name self.age = age self.phone_number = phone_number self.username = f"{self.first_name} {self.last_name}" def describe_user(self): print(f"user's name is {self.username}") print(f"{self.username} is {self.age} years old") print(f"{self.username}'s phone number is {self.phone_number}") def greet_user(self): print(f"Hello, {self.username}") user1 = User('xiong', 'jiajin', 13, 110) user1.describe_user() user1.greet_user()
注意:一个类中所有的变量都要在__init__()中定义并完成初始化
使用类和实例
类编写好后,你的大部分时间将花在使用根据类创建的实例上,你需要完成的首要任务之一是,修改实例的属性。
既可以直接修改实例的属性,也可以编写方法以特定的方式进行修改。
class Car: """一次模拟汽车的简单尝试""" def __init__(self, make, model, year): self.make = make self.model = model self.year = year def get_descriptive_name(self): """返回格式规范的描述性信息""" long_name = f"{self.year} {self.make} {self.model}" return long_name my_new_car = Car('audi', 'A6', 2023) print(my_new_car.get_descriptive_name())
给属性指定默认值
有些属性无须通过形参来定义,可以在__init__()方法中为其指定默认值,如下
class Car: """一次模拟汽车的简单尝试""" def __init__(self, make, model, year): self.make = make self.model = model self.year = year self.odometer_reading = 0 def get_descriptive_name(self): """返回格式规范的描述性信息""" long_name = f"{self.year} {self.make} {self.model}" return long_name def read_odometer(self): """打印一条指出汽车行驶里程的消息""" print(f"This car has {self.odometer_reading} miles on it") my_new_car = Car('audi', 'A6', 2023) print(my_new_car.get_descriptive_name()) my_new_car.read_odometer()
但是实际上出售时里程读表为0的汽车不多,因此需要修改改属性。
修改属性的值
可以用三种不同的方式修改属性的值:直接通过实例修改,通过方法设置,以及通过方法递增(增加特定的值)。下面一次介绍这些方式
①直接修改属性的值
要修改属性里的值,最简单方式是通过实例直接访问它
class Car: """一次模拟汽车的简单尝试""" def __init__(self, make, model, year): self.make = make self.model = model self.year = year self.odometer_reading = 0 def get_descriptive_name(self): """返回格式规范的描述性信息""" long_name = f"{self.year} {self.make} {self.model}" return long_name def read_odometer(self): """打印一条指出汽车行驶里程的消息""" print(f"This car has {self.odometer_reading} miles on it") my_new_car = Car('audi', 'A6', 2023) print(my_new_car.get_descriptive_name()) my_new_car.odometer_reading = 23 my_new_car.read_odometer()
②通过方法修改属性的值
class Car: """一次模拟汽车的简单尝试""" def __init__(self, make, model, year): self.make = make self.model = model self.year = year self.odometer_reading = 0 def get_descriptive_name(self): """返回格式规范的描述性信息""" long_name = f"{self.year} {self.make} {self.model}" return long_name def read_odometer(self): """打印一条指出汽车行驶里程的消息""" print(f"This car has {self.odometer_reading} miles on it") def update_odometer(self, mileage): """将里程表设置为指定的数""" self.odometer_reading = mileage my_new_car = Car('audi', 'A6', 2023) print(my_new_car.get_descriptive_name()) my_new_car.update_odometer(26) my_new_car.read_odometer()
还可以对update_odometer()方法进行扩展,使其在修改里程表读书时做一些额外的工作,比如添加一些逻辑,禁止里程表读数往回调整:
def update_odometer(self, mileage): """将里程表设置为指定的数""" self.odometer_reading = mileage if mileage >= self.odometer_reading: self.odometer_reading = mileage else: print("You can't roll back an odometer!")
③通过方法让属性的值递增
有时候需要将属性值递增特定的量,而不是将其设置为全新的值。
class Car: """一次模拟汽车的简单尝试""" def __init__(self, make, model, year): self.make = make self.model = model self.year = year self.odometer_reading = 0 def get_descriptive_name(self): """返回格式规范的描述性信息""" long_name = f"{self.year} {self.make} {self.model}" return long_name def read_odometer(self): """打印一条指出汽车行驶里程的消息""" print(f"This car has {self.odometer_reading} miles on it") def update_odometer(self, mileage): """将里程表设置为指定的数""" self.odometer_reading = mileage if mileage >= self.odometer_reading: self.odometer_reading = mileage else: print("You can't roll back an odometer!") def increment_odometer(self, miles): """让里程表读数增加指定的值""" self.odometer_reading += miles my_new_car = Car('audi', 'A6', 2023) print(my_new_car.get_descriptive_name()) my_new_car.update_odometer(26) my_new_car.read_odometer() my_new_car.increment_odometer(100) my_new_car.read_odometer()
练习9.4:
class Restaurant: def __init__(self, restaurant_name, cuisine_type): self.restaurant_name = restaurant_name self.cuisine_type = cuisine_type self.number_served = 0 def describe_restaurant(self): print(f"restaurant's name is {self.restaurant_name}") print(f"cuisine_type is {self.cuisine_type}") def open_restaurant(self): print(f"{self.restaurant_name.title()} is opening") def set_number_served(self, number_served_set): if number_served_set >= self.number_served: self.number_served = number_served_set else: print("you enter a wrong statistic") def increment_number_served(self, increment_number): if increment_number >= 0: self.number_served += increment_number else: print("the number input is less than zero") restaurant = Restaurant('dongbei BBQ', 'dun') restaurant.describe_restaurant() restaurant.open_restaurant() restaurant.number_served = 136 print(f"{restaurant.number_served} people have been served in {restaurant.restaurant_name}") restaurant.set_number_served(147) print(f"{restaurant.number_served} people have been served in {restaurant.restaurant_name}") restaurant.increment_number_served(9) print(f"{restaurant.number_served} people have been served in {restaurant.restaurant_name}")
练习9.5:
class User: def __init__(self, first_name, last_name, age, phone_number): self.first_name = first_name self.last_name = last_name self.age = age self.phone_number = phone_number self.username = f"{self.first_name} {self.last_name}" self.log_attempts = 0 def describe_user(self): print(f"user's name is {self.username}") print(f"{self.username} is {self.age} years old") print(f"{self.username}'s phone number is {self.phone_number}") def greet_user(self): print(f"Hello, {self.username}") def increment_login_attempts(self): self.log_attempts += 1 def reset_login_attempts(self): self.log_attempts = 0 user1 = User('xiong', 'jiajin', 13, 110) user1.describe_user() user1.greet_user() user1.increment_login_attempts() user1.increment_login_attempts() print(user1.log_attempts) user1.reset_login_attempts() print(user1.log_attempts)
继承:
在编写类时,并非总要从头开始,如果编写的类是一个既有的类的特殊版本,可以使用继承。当一个类继承另一个类。当一个类继承另一个类时,将自动获得后者的所有属性和方法。原有的类称为父类,而新类称为子类。子类不仅继承父类的所有属性和方法,还可以定义自己的属性和方法。
①子类__init__()方法
在既有的类的基础上编写新类,通常要调用父类的__init__()方法。这将初始化在父类的__init__()方法中定义的所有属性,从而让子类也可以使用这些属性。
class Car: """一次模拟汽车的简单尝试""" def __init__(self, make, model, year): self.make = make self.model = model self.year = year self.odometer_reading = 0 def get_descriptive_name(self): """返回格式规范的描述性信息""" long_name = f"{self.year} {self.make} {self.model}" return long_name def read_odometer(self): """打印一条指出汽车行驶里程的消息""" print(f"This car has {self.odometer_reading} miles on it") def update_odometer(self, mileage): """将里程表设置为指定的数""" self.odometer_reading = mileage if mileage >= self.odometer_reading: self.odometer_reading = mileage else: print("You can't roll back an odometer!") def increment_odometer(self, miles): """让里程表读数增加指定的值""" self.odometer_reading += miles class ElectricCar(Car): """电动汽车的独到之处""" def __int__(self, make ,model, year): """初始化父类的属性""" super().__init__(make, model, year) my_leaf = ElectricCar('nissan', 'leaf', 2023) print(my_leaf.get_descriptive_name())
在创建子类时,父类必须包含在当前文件中,并且位于子类的前面,在定义子类时,必须在括号内指定父类的名称,__init__()方法接受创建Car实例所需的信息。
super()是一个特殊的函数,让你能够调用父类的方法,从而让ElectricCar实例包含这个方法定义的所有属性,父类也称为超类,函数名super由此得名。
给子类定义属性和方法
让一个类继承另一个类后,就可以添加区分子类和父类所需的新属性和新方法
class Car: """一次模拟汽车的简单尝试""" def __init__(self, make, model, year): self.make = make self.model = model self.year = year self.odometer_reading = 0 def get_descriptive_name(self): """返回格式规范的描述性信息""" long_name = f"{self.year} {self.make} {self.model}" return long_name def read_odometer(self): """打印一条指出汽车行驶里程的消息""" print(f"This car has {self.odometer_reading} miles on it") def update_odometer(self, mileage): """将里程表设置为指定的数""" self.odometer_reading = mileage if mileage >= self.odometer_reading: self.odometer_reading = mileage else: print("You can't roll back an odometer!") def increment_odometer(self, miles): """让里程表读数增加指定的值""" self.odometer_reading += miles class ElectricCar(Car): """电动汽车的独到之处""" def __int__(self, make, model, year): """ 先初始化父类的属性,在初始化电动车特有的属性 """ super().__init__(make, model, year) self.battery_size = 20 def describe_battery(self): """打印一条描述电池容量的消息""" print(f"This car has a {self.battery_size}-kWh battery") my_leaf = ElectricCar('nissan', 'leaf', 2023) print(my_leaf.get_descriptive_name()) my_leaf.battery_size = 50 my_leaf.describe_battery()
重写父类中的方法:
再使用子类模拟实物的行为时,如果父类中的一些方法不能满足子类的需求,就可以用下面的办法重写:再子类中定义一个与要重写的父类方法同名的方法,这样Python将忽略这个父类方法,之关注你在子类中定义的相应方法。
将实例用作属性
在使用代码模拟实物时,你可能会发现自己给类添加了太多细节:属性和方法越来越多,文件越来越长。在这种情况下,可能需要将类的一部分提取出来,作为一个独立的类。将大型类拆分成多个协同工作的小类,这种方法称为组合。
一定要注意区分__init__() 和 __int__(),并且两边都是有两个下划线
例如:
class Car: """一次模拟汽车的简单尝试""" def __init__(self, make, model, year): self.make = make self.model = model self.year = year self.odometer_reading = 0 def get_descriptive_name(self): """返回格式规范的描述性信息""" long_name = f"{self.year} {self.make} {self.model}" return long_name def read_odometer(self): """打印一条指出汽车行驶里程的消息""" print(f"This car has {self.odometer_reading} miles on it") def update_odometer(self, mileage): """将里程表设置为指定的数""" self.odometer_reading = mileage if mileage >= self.odometer_reading: self.odometer_reading = mileage else: print("You can't roll back an odometer!") def increment_odometer(self, miles): """让里程表读数增加指定的值""" self.odometer_reading += miles class Battery: """一次模拟电动汽车电池的简单尝试""" def __init__(self, battery_size=40): self.battery_size = battery_size def describe_battery(self): """打印一条描述电池容量的消息""" print(f"This car has a {self.battery_size}-kWh battery.") class ElectricCar(Car): """电动汽车的独到之处""" def __init__(self, make, model, year): """ 先初始化父类的属性,在初始化电动车特有的属性 """ super().__init__(make, model, year) self.battery = Battery() my_leaf = ElectricCar('nissan', 'leaf', 2023) print(my_leaf.get_descriptive_name()) my_leaf.battery.describe_battery()
我们定义了一个名为Battery的新类,它没有继承任何类,__init__()方法在self之外还有一个形参battery_size。这个形参是可选的:如果没有给它提供值,电池容量将被设置为40,describe_battery()方法也被移到了这个类中。
在ElectricCar类中,添加一个名为self.battery的属性,这行代码让Python创建一个新的Battery实例(因为没有指定容量,所以默认值为40),并将该实例赋给属性self.battery。每当__init__()方法被调用时,都将执行该操作,因此现在每个ElectricCar实例都包含一个自动创建的Battery实例。
这看似做了很多额外的工作,但是现在想多详细地描述电池都可以,且不会导致ElectricCar类混乱不堪。
下面再给Battery类添加一个方法,它更具电池容量报告汽车的续航里程:
class Car: """一次模拟汽车的简单尝试""" def __init__(self, make, model, year): self.make = make self.model = model self.year = year self.odometer_reading = 0 def get_descriptive_name(self): """返回格式规范的描述性信息""" long_name = f"{self.year} {self.make} {self.model}" return long_name def read_odometer(self): """打印一条指出汽车行驶里程的消息""" print(f"This car has {self.odometer_reading} miles on it") def update_odometer(self, mileage): """将里程表设置为指定的数""" self.odometer_reading = mileage if mileage >= self.odometer_reading: self.odometer_reading = mileage else: print("You can't roll back an odometer!") def increment_odometer(self, miles): """让里程表读数增加指定的值""" self.odometer_reading += miles class Battery: """一次模拟电动汽车电池的简单尝试""" def __init__(self, battery_size=40): self.battery_size = battery_size def describe_battery(self): """打印一条描述电池容量的消息""" print(f"This car has a {self.battery_size}-kWh battery.") def get_range(self): """打印一条消息,指出电池的续航里程""" if self.battery_size == 40: range = 150 elif self.battery_size ==65: range =225 print(f"This car can go about {range} miles on a full charge") class ElectricCar(Car): """电动汽车的独到之处""" def __init__(self, make, model, year): """ 先初始化父类的属性,在初始化电动车特有的属性 """ super().__init__(make, model, year) self.battery = Battery(65) my_leaf = ElectricCar('nissan', 'leaf', 2023) print(my_leaf.get_descriptive_name()) my_leaf.battery.describe_battery() my_leaf.battery.get_range()
模拟实物:
对现实世界的建模方法没有对错之分,有些方法的效率更高,但要找出效率最高的表示法,需要一定的实践,只要代码能够像你希望的那样运行,就说明你已经做得很好了!
练习9.6
class Restaurant: def __init__(self,restaurant_name,cuisine_type): self.restaurant_name = restaurant_name self.cuisine_type = cuisine_type self.flavors = ['orange', 'milk', 'apple'] def describe_restaurant(self): print(f"restaurant's name is {self.restaurant_name}") print(f"cuisine_type is {self.cuisine_type}") def open_restaurant(self): print(f"{self.restaurant_name.title()} is opening") def describe_flavor(self): for flavor in self.flavors: print(f"{self.restaurant_name} provide {flavor} ice-cream") restaurant = Restaurant('dongbei BBQ', 'dun') restaurant.describe_restaurant() restaurant.open_restaurant() IceCreamStand = Restaurant('蜜雪冰城', '冰淇淋店') IceCreamStand.describe_flavor()
练习9.7
class User: def __init__(self, first_name, last_name, age, phone_number): self.first_name = first_name self.last_name = last_name self.age = age self.phone_number = phone_number self.username = f"{self.first_name} {self.last_name}" self.log_attempts = 0 self.privileges = ['can add post', 'can delete post', 'can ban user'] def describe_user(self): print(f"user's name is {self.username}") print(f"{self.username} is {self.age} years old") print(f"{self.username}'s phone number is {self.phone_number}") def greet_user(self): print(f"Hello, {self.username}") def increment_login_attempts(self): self.log_attempts += 1 def reset_login_attempts(self): self.log_attempts = 0 def show_privileges(self): for privilege in self.privileges: print(f"{self.username}'s privileges include {privilege}") user1 = User('xiong', 'jiajin', 13, 110) user1.show_privileges()
练习9.8
class User: def __init__(self, first_name, last_name, age, phone_number): self.first_name = first_name self.last_name = last_name self.age = age self.phone_number = phone_number self.username = f"{self.first_name} {self.last_name}" self.log_attempts = 0 def describe_user(self): print(f"user's name is {self.username}") print(f"{self.username} is {self.age} years old") print(f"{self.username}'s phone number is {self.phone_number}") def greet_user(self): print(f"Hello, {self.username}") def increment_login_attempts(self): self.log_attempts += 1 def reset_login_attempts(self): self.log_attempts = 0 class Privileges: def __init__(self): self.privileges = ['can add post', 'can delete post', 'can ban user'] def show_privileges(self): for privilege in self.privileges: print(f"manager's privileges include {privilege}") class Admin(User): def __init__(self, first_name, last_name, age, phone_number): super().__init__(first_name, last_name, age, phone_number) self.privilege = Privileges() user1 = Admin('xiong', 'jiajin', 13, 110) user1.privilege.show_privileges()
super().__init__()后面不含有self
练习9.9
class Car: """一次模拟汽车的简单尝试""" def __init__(self, make, model, year): self.make = make self.model = model self.year = year self.odometer_reading = 0 def get_descriptive_name(self): """返回格式规范的描述性信息""" long_name = f"{self.year} {self.make} {self.model}" return long_name def read_odometer(self): """打印一条指出汽车行驶里程的消息""" print(f"This car has {self.odometer_reading} miles on it") def update_odometer(self, mileage): """将里程表设置为指定的数""" self.odometer_reading = mileage if mileage >= self.odometer_reading: self.odometer_reading = mileage else: print("You can't roll back an odometer!") def increment_odometer(self, miles): """让里程表读数增加指定的值""" self.odometer_reading += miles class Battery: """一次模拟电动汽车电池的简单尝试""" def __init__(self, battery_size=40): self.battery_size = battery_size def describe_battery(self): """打印一条描述电池容量的消息""" print(f"This car has a {self.battery_size}-kWh battery.") def get_range(self): """打印一条消息,指出电池的续航里程""" if self.battery_size == 40: range = 150 elif self.battery_size ==65: range =225 print(f"This car can go about {range} miles on a full charge") def upgrade_battery(self): if self.battery_size != 65: self.battery_size = 65 class ElectricCar(Car): """电动汽车的独到之处""" def __init__(self, make, model, year): """ 先初始化父类的属性,在初始化电动车特有的属性 """ super().__init__(make, model, year) self.battery = Battery(40) my_leaf = ElectricCar('nissan', 'leaf', 2023) print(my_leaf.get_descriptive_name()) my_leaf.battery.describe_battery() my_leaf.battery.get_range() my_leaf.battery.upgrade_battery() my_leaf.battery.get_range()
导入类:
①导入单个类
car.py
class Car: """一次模拟汽车的简单尝试""" def __init__(self, make, model, year): self.make = make self.model = model self.year = year self.odometer_reading = 0 def get_descriptive_name(self): """返回格式规范的描述性信息""" long_name = f"{self.year} {self.make} {self.model}" return long_name def read_odometer(self): """打印一条指出汽车行驶里程的消息""" print(f"This car has {self.odometer_reading} miles on it") def update_odometer(self, mileage): """将里程表设置为指定的数""" self.odometer_reading = mileage if mileage >= self.odometer_reading: self.odometer_reading = mileage else: print("You can't roll back an odometer!") def increment_odometer(self, miles): """让里程表读数增加指定的值""" self.odometer_reading += miles
允许将类存储在模块中,然后再主程序中导入所需的模块
my_car.py
from car import Car my_new_car = Car('audi', 'A6', '2024') print(my_new_car.get_descriptive_name()) my_new_car.odometer_reading = 23 my_new_car.read_odometer()
从car.py中导入类Car,这让你的主程序文件变得整洁易读,还让你能够将大部分逻辑存储在独立的文件中。
②在一个模版中存储多个类
尽管同一个模块中的类之间应该存在某种相关性,但其实可以根据需要在一个模块中存储任意数量的类。Battery类和ElectricCar类都可帮助模拟汽车,下面将它们都加入模块car.py
car.py
class Car: """一次模拟汽车的简单尝试""" def __init__(self, make, model, year): self.make = make self.model = model self.year = year self.odometer_reading = 0 def get_descriptive_name(self): """返回格式规范的描述性信息""" long_name = f"{self.year} {self.make} {self.model}" return long_name def read_odometer(self): """打印一条指出汽车行驶里程的消息""" print(f"This car has {self.odometer_reading} miles on it") def update_odometer(self, mileage): """将里程表设置为指定的数""" self.odometer_reading = mileage if mileage >= self.odometer_reading: self.odometer_reading = mileage else: print("You can't roll back an odometer!") def increment_odometer(self, miles): """让里程表读数增加指定的值""" self.odometer_reading += miles class Battery: """一次模拟电动汽车电池的简单尝试""" def __init__(self, battery_size=40): self.battery_size = battery_size def describe_battery(self): """打印一条描述电池容量的消息""" print(f"This car has a {self.battery_size}-kWh battery.") def get_range(self): """打印一条消息,指出电池的续航里程""" if self.battery_size == 40: range = 150 elif self.battery_size ==65: range =225 print(f"This car can go about {range} miles on a full charge") def upgrade_battery(self): if self.battery_size != 65: self.battery_size = 65 class ElectricCar(Car): """电动汽车的独到之处""" def __init__(self, make, model, year): """ 先初始化父类的属性,在初始化电动车特有的属性 """ super().__init__(make, model, year) self.battery = Battery()
主程序:
my_car.py
from car import ElectricCar my_leaf = ElectricCar('nissan', 'leaf', 2024) print(my_leaf.get_descriptive_name()) my_leaf.battery.describe_battery() my_leaf.battery.get_range()
从一个模块中导入多个类:
可以根据需要再程序文件中导入任意数量的类。如果要在同一个程序中创建燃油汽车和电动汽车,就需要将Car类和ElectricCar类都引入
from car import ElectricCar,Car my_leaf = ElectricCar('nissan', 'leaf', 2024) print(my_leaf.get_descriptive_name()) my_leaf.battery.describe_battery() my_leaf.battery.get_range() my_mustang = Car('ford', 'mustang', 2024) print(my_mustang.get_descriptive_name())
当从一个模块中导入多个类时,用逗号分隔各个类。导入必要的类后,就可根据需要创建每个类的任意数量的实例了
导入整个模块
还可以先导入整个模块,再使用点好访问需要的类。这种导入方法很简单,代码也易读,由于创建类实例的代码都包含模块名,因此不会与当前文件使用的任何名称发生冲突。
import car my_leaf = car.ElectricCar('nissan', 'leaf', 2024) print(my_leaf.get_descriptive_name()) my_leaf.battery.describe_battery() my_leaf.battery.get_range() my_mustang = car.Car('ford', 'mustang', 2024) print(my_mustang.get_descriptive_name())
导入模块中的所有类:
要导入模块中的每个类,可使用下面的语法:
from module_name import *
不推荐这种导入方式:
一方面最好只看一下文件开头的import语句,就能清楚地知道程序使用了哪些类,但这种导入方式没有明确地指出使用了模块中的哪些类。
另一方面,这种导入方式还可能引发名称方面的迷惑,如果一不小心导入了一个与程序文件中的其他东西同名的类,将引发难易诊断的错误。
但是我们还是要去了解这种导入方式,因为我们可能在别人编写的代码中见到它
在一个模块中导入另一个模块
有时候,需要将类分散到多个模块中,以免模块太大或者在同一个模块中存储不相关的类,在将类存储在多个模块中时,你可能会发现一个模块中的类依赖于另一个模块中的类,在这种情况下,可在前一个模块中导入必要的类。
现在可以分别从每个模块中导入类,以根据需要创建任意类型的汽车了
from car import Car
from electric_car import ElectriCar
使用别名
给类指定别名
from electric_car import ElectricCar as EC
给模块指定别名
import electric_car as ec
找到合适的工作流程
一开始应让代码结构尽量简单,首先尝试在一个文件中完成所有的工作,确定一切都能正确运行后,在将类移到独立的模块中国,如果你喜欢模块和文件的交互方式,可在项目开始时就尝试将类存储到模块中。先找出让你能够编写出可行代码的方式,再尝试让代码更加整洁。
练习9.11
import statistic user1 = statistic.Admin('xiong', 'haha', 18, 110) user1.privilege.show_privileges()
练习9.12
statistic.py
class User: def __init__(self, first_name, last_name, age, phone_number): self.first_name = first_name self.last_name = last_name self.age = age self.phone_number = phone_number self.username = f"{self.first_name} {self.last_name}" self.log_attempts = 0 def describe_user(self): print(f"user's name is {self.username}") print(f"{self.username} is {self.age} years old") print(f"{self.username}'s phone number is {self.phone_number}") def greet_user(self): print(f"Hello, {self.username}") def increment_login_attempts(self): self.log_attempts += 1 def reset_login_attempts(self): self.log_attempts = 0
admin.py
import statistic class Privileges: def __init__(self): self.privileges = ['can add post', 'can delete post', 'can ban user'] def show_privileges(self): for privilege in self.privileges: print(f"manager's privileges include {privilege}") class Admin(statistic.User): def __init__(self, first_name, last_name, age, phone_number): super().__init__(first_name, last_name, age, phone_number) self.privilege = Privileges()
main_idea.py
import admin user1 = admin.Admin('xiong', 'haha', 18, 110) user1.privilege.show_privileges()
Python标准库
python标准库是一组模块,在安装Python时以及包含在内。
我们可以使用标准库中的任何函数和类,只需在程序开头添加一条简单的import语句即可
例如模块random:
random中的一个有趣的函数是randint()。她将两个整数作为参数,并随机返回一个位于这两个整数之间(含)的整数。
from random import randint print(randint(1, 6))
另一个很有用的参数是choice(),它将一个列表或元组作为参数,并随机返回其中一个元素
from random import choice players = ['LBL', 'kari', 'KOBE', 'jordan'] first_up = choice(players) print(first_up)
还可以从其他地方下载外部模块!
练习9.13
from random import randint class Die: def __init__(self, sides): self.sides = sides def roll_die(self): print(randint(1, self.sides)) die1 = Die(6) die1.roll_die() die2 = Die(10) die2.roll_die() die3 = Die(20) die3.roll_die()
练习9.14
from random import choice statis = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'x', 'l', 'j', 'z', 'h'] def open_result(group): number = 0 while number < 4: number += 1 print(choice(group)) open_result(statis)
练习9.15
from random import choice statis = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'x', 'l', 'j', 'z', 'h'] my_ticket = ['x', 'j', '3', '0'] def open_result(group): price_result = [] number = 0 while number < 4: number += 1 price_result.append(choice(group)) print(price_result) return price_result number1 = 0 open_number = [] while open_number != my_ticket: number1 += 1 open_number = open_result(statis) print(f"循环了{number1}次才中奖了")
要了解Python标准库,一个很不错的资源是网站Python 3 Module of the Week
类的编程风格
类名应采用驼峰命名法,即将类名中的每个单词的首字母都大写,并且不适用下划线。
实例名和模块名都采用全小写格式,并在单词之间加上下划线。
对于每个类,都应该在类定义后面紧跟一个文档字符串,简要地描述类的功能。
每个模块后也都应包含一个文档字符串,对其中的类可用来做什么进行描述
在类中,可以使用一个空行来分隔方法
在模块中,可以使用两个空行来分隔类
当需要同时导入标准库中的模块和你编写的模块时,先编写导入标准模块的import语句,再添加一个空行,然后编写导入你自己编写的模块的import语句。这样让人更容易明白程序使用的模块来自哪里
标签:__,入门,Python,self,odometer,第九章,print,def,name From: https://blog.csdn.net/a_bear_in_Spring/article/details/136783216