第七章 类与可口可乐
7.1 定义一个类
类是有一些系列有共同特征和行为事物的抽象概念的总和。
在类里面赋值的变量就是类的变量,而类的变量有一个专有的术语,我们称之为类的属性(Class Atrribute)。
这里举例可乐为类,可乐的配方为类的属性,用Python来表示
class Cocacola:
formula = ['caffeine','sugar', 'water', 'soda']
7.2 类的实例化
在左边我们创建一个变量,右边写上类的名称,这样看起来很像是赋值的行为,我们称之为类的实例化。而被实例化后的对象,我们称之为实例(instance),或者说是类的实例。对于可乐来说,按照配方把可乐生产出来的过程就是实例化的过程。
coke_for_me = CocaCola()
coke_for_you = CocaCola()
7.3 类属性引用
在类的名字后面输入 .,IDE 就会自动联想出我们之前在定义类的时候写在里面的属性,而这就是类属性的引用(attribute references)。
CocaCola.formula
类的属性会被所有类的实例共享,所以当你在类的实例后面再点上 . ,索引用的属性值是完全一样的。
coke_for_me.formula
coke_for_you.formula
上面的意思是不管是谁的可乐,只要是可乐这个类里面的,都得按这个配方生产,所以这三个可乐配方是一样的
7.4 实例属性
你的可乐叫Cocacola,我的叫可口可乐,但是都是可乐,味道是一样的,只是叫法不同,不同叫法是不同实例的属性,用Python来表示
coke_for_china = Cocacola()
coke_for_china.local_logo = '可口可乐' # 创建实例属性
print(coke_for_china.local_logo) # 打印实例属性引用结果
# 可口可乐
通过上面的代码,我们给在中国生产的可口可乐贴上了中文字样的“可口可乐”标签——在创建了类之后,通过 object.new_atrr 的形式进行一个赋值,于是我们就得到了一个新的实例的变量,实例的变量就是实例变量,而实例变量有一个专有的术语,我们称之为实例属性(Instance Atrribute)。
7.5 畅爽开怀,实例方法
可乐可以用来干什么呢?额,当然是拿来喝了,你的可乐和我的可乐都可以用来喝,‘喝’可以看做是方法,你喝,我喝,就是实例方法了,用Python来表示是这样
class Cocacola():
formula = ['caffeine', 'sugar', 'water', 'soda']
def drink(self):
print('Energy')
coke_for_china = Cocacola()
coke_for_USA = Cocacola()
coke_for_china.local_logo = '可口可乐' # 创建实例属性
print(coke_for_china.local_logo) # 打印实例属性引用结果
print(coke_for_china.drink()) # 打印实例方法
print(coke_for_USA.drink())
7.6 更多参数
和函数一样,类的方法也能有属于自己的参数,我们先来试着在 .drink() 方法上做些改动:
class CocaCola:
formula = ['caffeine','sugar','water','soda']
def drink(self,how_much):
if how_much == 'a sip':
print('Cool~')
elif how_much == 'whole bottle':
print('Headache!')
ice_coke = CocaCola()
ice_coke.drink('a sip')
# Cool~
7.7 魔术方法
Python 的类中存在一些方法,被称为"魔术方法",init() 就是其中之一。
_init() 的神奇之处就在于,如果你在类里定义了它,在创建实例的时候它就能帮你自动地处理很多事情——比如新增实例属性。在上面的代码中,我们创建了一个实例属性,但那是在定义完类之后再做的,这次我们一步到位:
class Cocacola():
def __init__(self):
self.local_logo = '可口可乐'
def drink(self, how_much):
if how_much == 'a sip':
print('Cool~')
elif how_much == 'whole bottle':
print('Headache')
coke = Cocacola()
print(coke.local_logo)
# 可口可乐
其实init()是 initialize(初始化)的缩写,这也就意味着即使我们在创建实例的时候不去引用 init()方法,其中的命令也会先被自动地执行。是不是感觉像变魔术一样?
init() 方法可以给类的使用提供极大的灵活性。试试看下面的代码会发生什么:
class Cocacola():
formula = ['caffeine', 'sugar', 'water', 'soda']
def __init__(self):
for element in self.formula:
print('Coke has {}!'.format(element))
def drink(self):
print('Energy!')
coke = Cocacola()
#Coke has caffeine!
#Coke has sugar!
#Coke has water!
#Coke has soda!
除了必写的self 参数之外,init() 同样可以有自己的参数,同时也不需要这样obj.init()的方式来调用(因为是自动执行),而是在实例化的时候往类后面的括号中放进参数,相应的所有参数都会传递到这个特殊的 init() 方法中,和函数的参数的用法完全相同。
class Cocacola():
formula = ['caffeine', 'sugar', 'water', 'soda']
def __init__(self,local_name):
self.local_logo = local_name
def drink(self):
print('Energy!')
coke = Cocacola('可口可乐')
print(coke.local_logo)
# 可口可乐
7.8 类的继承
可口可乐又衍生出好多口味,像零度、荔枝味、无咖的……,这些衍生出的口味我们管他叫子类,可口可乐我们管它叫父类,子类会继承父类的属性,但子类有变化时会覆盖父类的属性,试着用Python来表示是这样的
class Cocacola():
calories = 140
sodium = 45
total_carb = 39
caffeine = 34
ingredients = [
'High Fructose Corn Syrup',
'Carbonated Water',
'Phosphoric Acid',
'Natural Flavors',
'Caramel Color',
'Caffeine'
]
def __init__(self, logo_name):
self.local_logo = logo_name
def drink(self):
print('You got {} cal energy!'.format(self.calories))
coke = Cocacola('可口可乐')
coke.drink()
# You got 140 cal energy!
class CaffeineFree(Cocacola):
caffeine = 0
ingredients = [
'High Fructose Corn Syrup',
'Carbonated Water',
'Phosphoric Acid',
'Natural Flavors',
'Caramel Color',
]
coke_a = CaffeineFree('Cocacola-FREE')
coke_a.drink()
print(coke_a.caffeine)
print(coke.caffeine)
# You got 140 cal energy!
# 0
# 34
当实例开始引用属性时,首先看有没有实例属性,有则引用实例属性,没有实例属性,看有没有类属性,有则引用,没有就报错了。