关于Python 类的属性及其 方法的参数类型 的一些要点

it2022-05-05  183

class Car(): """一次模拟汽车的简单尝试""" def __init__(self, make, model, year=2016): """初始化描述汽车点的属性""" self.make = make self.model = model self.year = year self.odometer_reading = 0 def get_descriptive_name(self,mileage): """返回整洁的描述性信息""" long_name =self.make + " " + str(self.year) + ' ' + self.model + ' ' +str(self.odometer_reading) + ' ' + srt(mileage) return long_name.title()

调用一个方法,需要注意两点:首先要保证其中的每个参数都有值,其次是每个参数值都是你想要的值。

方法get_descriptive_name(),其结果简单,但包含的5个参数属于多种类型(A、B、C、D): (B)(C)属于给类属性设置默认值的两种不同方式 凡是通过__init__()函数进行初始化的变量都是类的属性,不管其有没有默认值,更不管设置默认值的方式 这五个参数中__init__()函数函数下的四个变量都是类Car的属性。但是mileage不是。

(A):如make, model,属于类的属性,而且是最普通最常见的情况。就按部就班地初始化,然后等实例给其提供值;

(B)如year,属于类的属性,但是属性year是在形参列表中将该属性设置为可选的,而且其初始化的过程同make, model并没有区别,等号右边仍然是形参year,而不是2016;

self.year = year

(C):如odometer_reading,属于类的属性,但是在初始化过程中设置了默认值,其等号右边不是形参odometer_reading,而是一个数字0(以这种方式设置默认值的属性,不能放到方法__init__()的括号中,但是它仍然是类Car的属性。正因为它是不在形参列表中的类的属性, 所以它的初始值必须要明确:必须是数字和带引号的字符串那种, 还可以是一个实例(P150下的类Battery的实例Battery()被用作了类ElectricCar的属性battery的初始值。(其实这里的类Battery的实例Battery()的名称与ElectricCar的属性battery用不同的名字表示也可以,没有规定他们必须相同。但是大小写一定要弄对,尤其是大写。他这里没有给类Battery的实例起小写名字,所以用的等号左边的大写))。 反正是要求能实实在在地给这个属性(属性的本质也是一个变量)赋上一个初始值)。

self.odometer_reading = 0

(D):如mileage,不属于类的属性,它是方法get_descriptive_name()方法独有的形参,在引用该方法时,在其后面括号中单独列出即可(100),这跟普通函数提供实参的方式相同。(因为该方法最后会通过return返回一个值,所以调用时必须要用print括起来)

print(my_used_car.get_descriptive_name(100))

在知道了类方法中的参数有哪几种后,就要将关注点放在函数上:根据某个函数中每个参数的不同情况去处理各个参数,而不是根据参数的不同类型去划分函数。因为我们要用函数去完成任务,而不是仅仅将参数分类。

回到文章开头的问题: 调用一个方法,首先要保证其中的每个参数都有值;其次是每个参数值都是你想要的值,不是的话,则要修改为你想要的。而且要根据参数的不同情况选则相应的方法去修改。

首先明确一点,对所有的属性的值,都可以通过《Python编程从入门到实践》P144下9.2.3提供的三种方式修改。其中最简单就是句点表示法直接访问并修改。 注意,是对属性,不是类属性的不能这么修改(比如mileage,见下面)

我们一个参数一个参数地看:

对(A),当你创建类Car的实例时,通常会直接提供这两个属性make, model的值,这不用多说。 如果要修改他们值,可以创建一个新的实例,或者用《Python编程从入门到实践》P144下9.2.3提供的三种方式修改即可。(根据需要选择方法,或者哪种简单选哪种也行)

对(B)year,在形参列表中将该属性设置为可选的。 ①当你不需要修改属性year的默认值(初始值)时,创建的实例时直接不提供year的值即可。其实写上也行,但意义不大。都无妨,关键是自己要清楚。

my_used_car = Car('subaru', 'outback')

这样在你后面的操作中,凡是用到my_used_car.year的(属性year),它的值都是2016 ②当你需要修改属性year的默认值(初始值)时,创建实例时直接你需要的year的值提供上即可。比如你要将year从默认值2016修改为2013.或者同样可以用《Python编程从入门到实践》P144下9.2.3提供的三种方式修改。(根据需要选择方法,或者哪种简单选哪种也行)

my_used_car = Car('subaru', 'outback',2013)

总结:对方法get_descriptive_name()中的(B)类参数,你通常可以通过上面两种创建实例的方式提供。关键是知道自己是否要修改其中的可选形参year即可。

对(C),同样分为修改和不修改属性odometer_reading的初始值两种情况。 ①当你不需要修改属性odometer_reading的默认值(0)时,调用这个方法时,直接调即可。因为它本身有值并且是你想要的值:

my_used_car = Car('subaru', 'outback',2013) print(my_used_car.get_descriptive_name(100))

②当你需要修改属性odometer_reading的默认值时,需要用《Python编程从入门到实践》P144下9.2.3提供的三种方式修改。 下面演示用最简单的句点表示法修改并调用函数(这或许就是修改这种属性最简单的方式了,没有比这更简单的了):

my_used_car = Car('subaru', 'outback',2013) my_used_car.odometer_reading = 25300 print(my_used_car.get_descriptive_name(100))

有默认值的形参,能传递任意数量实参的形参,要放在列表最后(P118下,P122,P130,P131)。这个规定同样也适用于类中的方法。

对(D),mileage,因为它是你方法中特有的形参,所以你需要什么直接在方法后面的括号中提供什么即可。要修改的话,也就直接修改并再次提供即可(后面两行):

my_used_car = Car('subaru', 'outback',2013) my_used_car.odometer_reading = 25300 print(my_used_car.get_descriptive_name(100)) print(my_used_car.get_descriptive_name(200))

创建实例时也要注意,你需要提供几个以及哪几个属性,他们各自的值又各为多少。

上面阐述的所有内容同样也使用与子类的属性及其方法。

#创建父类 class Car(): """一次模拟汽车的简单尝试""" def __init__(self,make,model,tank_capacity,year=2016): """初始化描述汽车的属性""" self.make = make self.model = model self.tank_capacity = tank_capacity self.year = year self.odometer_reading = 0 #创建子类(继承) class ElectricCar(Car): """电动汽车的独特之处""" def __init__(self,make,model,tank_capacity,year,battery_size=100): """先初始化父类的属性,,再初始化电动汽车的特有属性""" super().__init__(make,model,tank_capacity,year) self.battery_size = battery_size

上面的类中: 父类/超类Car一共有五个属性: ①make,②model,③tank_capacity,④year,⑤odometer_reading

其中④year和⑤odometer_reading分别采用了两种不同的方式设置了默认值(所有没有⑤)。因此在创建实例过程中要注意其属性的个数及如何修改属性的默认值。

子类ElectricCar一共有六个属性: 除了继承的父类的全部属性外(五个),自己还有特有的一个属性⑥battery_size,而且⑥采用了第一种设置默认值的方式给其设置了默认值。 注意,除了 用第二种方式设置默认值 (不管是父类的还是子类的)不写在形参列表中,其余的属性都要写进类ElectricCar的形参列表中。 这时,创建类ElectricCar的实例和修改其属性的值情况将会变得更加复杂,所以要细心点并且思维逻辑要清楚。 注意创建类ElectricCar的实例时,对属性year必须要指出其值。虽然year属性已经在其父类Car中提供了默认值并且是第一种方式,但是并不能再在子类ElectricCar中沿用。而且因为子类ElectricCar并没有以任何方式设置其默认值,所以必须在其实例中明确指出来。

这说明:各自看各自的属性有哪几个,分别怎么写。父类看父类的,子类看子类的,他们之间创建实例时没有多大关系,只是公用属性和方法。

即:

my_tesla = ElectricCar("tesila", "model-L", 70,2013)

有时候,类的属性会更多,而且就如上面所示,还会采用不同的方式设置默认值。如果涉及到子类那么情况会更复杂,所以不仅要清楚其中的每个小知识点,还要有清晰的逻辑思维。

创建实例时的原则(下面的前三个顺序是方法__init__形参列表的顺序,也是实例实参的顺序): ①凡是不设置默认值的,必须要提供实参; 注意:做属性的变量不仅可以是:数字,带引号的字符串,还可以是:列表,元组,字典。在方法中做变量前面一定要加self.

②凡是以第一种方式设置默认值的,如果要修改就提供,如果不修改就别提供; 注意:做属性的变量不仅可以是:数字,带引号的字符串,还可以是:列表,元组,字典。在方法中做变量前面一定要加self.

特殊情况:当以第一种方式设置默认值的形参(属性)后面跟的是 传递任意数量的实参时(如加 * 和 * *)(他们也是属性),一定要提供,不修改也要提供其默认值,不然就会使它接受的实参少一个。(而且是元组时还没办法增加或删除元素) 上面的笔记我可以保证绝对没错,但有时候实在不行,还可以用试的方法,直到结果像自己想的那样输出了。

③类中方法__init__()的形参列表中也可以有列表和字典,同样也需要在最后(《Python编程从入门到实践》P130,加一个*使py创建空元组,加**使py创建空字典),需要注意的就是上面的②的一些情况; 注意:做属性的变量不仅可以是:数字,带引号的字符串,还可以是:列表,元组,字典。

下面的是不能出现在方法__init__形参列表,也不能出现在是实例实参列表中: ④凡是以第二种顺序设置默认值的,就一定不能出现在上面的两个列表中

注意:做属性的变量不仅可以是:数字,带引号的字符串,还可以是:列表,元组,字典。在方法中做变量前面一定要加self. 只不过创建实例时,可变对象 最好提前声明(列表,字典)。就像下面的列表flavors_1一样。 而不可变对象(数字,带引号的字符串,元组(元组最好也提前声明))只要不是以第二种方式设置默认值的就可以直接体现在实例实参列表中。就像其中的"BAXY","Ice Cream"一样。

类中的最基本结构就是def(定义方法),所以函数中的一切原则及规定都要同步到类中每一个def中。 上面的顺序就如课本第八章P131上总结的顺序一样,也必须都要按照《Python编程从入门到实践》第八章P131上的顺序(或者上面的顺序)。

上边②的特殊情况说明: 特殊情况:当以第一种方式设置默认值的形参(属性)后面跟的是 传递任意数量的实参时(如加 * 和 * *)(他们也是属性),一定要提供,不修改也要提供其默认值,不然就会使它接受的实参少一个。(而且是元组时还没办法增加或删除元素)。

这个在单纯的函数中(不是在类中的方法)也同样适用。只不过看《Python编程从入门到实践》第八章的时候没总结出来,到第九章才发现的。

而且上面有那么强调创建实例时实参的顺序,也是因为创建实例后调用方法时就是遵循的像函数传递实参的方式——位置实参(《Python编程从入门到实践》P116中),所以创建实例时实参的顺序一定要清楚。如果实在复杂,也同样可以试用关键字实参方式传递参数(P118中)

类是比函数大很多很多的东西,函数相对于类来说是很小的细节。


最新回复(0)