类
– 在美国所有人喝到的可口可乐都是一样的,无论是总统还是流浪汉。Andy Warhol
定义一个类
定义:类是有一些系列有共同特征的行为事务的抽象概念的总和
# 小例子:定义一个可口可乐类,赋予一个配方变量
class CocaCola:
formula = ['caffine', 'sugar', 'water', 'soda']
可以看到这个类中有一个列表变量
formula
,在类中赋值的变量就是类的变量,称为类的属性。
类的实例化
coke_for_me = CocaCola()
coke_for_you = CocaCola()
print(CocaCola.formula)
print(coke_for_me.formula)
print(coke_for_you.formula)
['caffine', 'sugar', 'water', 'soda']
['caffine', 'sugar', 'water', 'soda']
['caffine', 'sugar', 'water', 'soda']
给类起一个名字,这很像将类赋值给一个变量,这种行为称之为类的实例化,而被实例化后的对象成为实例或类的实例。
类属性引用
print(CocaCola.formula)
print(coke_for_me.formula)
print(coke_for_you.formula)
['caffine', 'sugar', 'water', 'soda']
['caffine', 'sugar', 'water', 'soda']
['caffine', 'sugar', 'water', 'soda']
如上所示,在类名后面输入
.
,然后输入类的属性的名称,这就是类属性引用。同时还可以发现,所有类的实例共享类的属性。
类的属性与正常变量没有区别,如:
for element in coke_for_me.formula:
print(element)
caffine
sugar
water
soda
在上面的这个例子中可以看出,类的这个属性是个列表变量,和正常的列表是一样的。
实例属性
class CocaCola:
formula = ['caffeine', 'sugar', 'water', 'soda']
coke_for_China = CocaCola()
coke_for_China.local_logo = '可口可乐' # 创建实例属性
print(coke_for_China.local_logo) # 打印实例属性引用结果
可口可乐
local_logo
这个属性属于coke_for_China
这个类的实例,是它所特有的,我们称之为实例属性;同时coke_for_China
这个类的实例也具有CocaCola
类的其他属性。
实例方法
类的实例可以引用属性,类的实例也可以使用方法。方法即函数,在这里我们称之为方法。方法是供类的实例使用的,所以也称之为实例方法。(方法即功能)
class CocaCola:
formula = ['caffeine', 'sugar', 'water', 'soda']
def drink(self):
print('Energy')
coke = CocaCola()
coke.drink() # 调用drink这个函数,其功能是打印'Energy'
Energy
上面的例子中self
是干嘛用的? 来看下面的例子
class CocaCola:
formula = ['caffine', 'sugar', 'water', 'soda']
def drink(coke):
print('Energy')
coke = CocaCola()
coke.drink()
Energy
可以看出两段代码功能相同,输出结果一致,可以看出
self
这个参数就是被创建的类的实例本身。
coke = CocaCola()
coke.drink() == CocaCola.drink(coke) # 左右两边的写法完全一致
Energy
Energy
True
函数的使用方法是将一个个对象作为参数放入函数的括号内,一旦一个类被实例化,那么我们的使用方式与使用类的方式相似。右边:
CocaCola
使用方法(函数/功能)drink
它需要参数,这个参数就是coke
这个实例本身,这就是self
,也可以写作其他,但习惯写self
,所以建议统一写self
。被实例化的对象会被编译器传入到后面的方法中,作为第一个参数。
更多参数
与函数相同,类的方法也可以有属于自己的参数,如试着给.drink()
方法增加一个how_much
参数:
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~
“魔术方法”
Python
的类中存在一些方法,被成为“魔术方法”,__init__()
是其中之一。
class CocaCola():
formula = ['caffeine', 'sugar', 'water', 'soda']
def __init__(self):
self.local_logo = '可口可乐'
def drink(self):
print('Energy')
coke = CocaCola()
print(coke.local_logo)
可口可乐
在
CocaCola()
这个类创建时,就创建了一个实例属性local_logo
,并且可以看出:在创建实例时,没有引用__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__()
的方式来调用,同样是自动执行的。而在实例化时往括号中self
后面放入的参数都会传入到“魔法方法”__init__()
中,和函数的参数用法完全相同。
class CocaCola():
formula = ['caffeine', 'sugar', 'water', 'soda']
def __init__(self, logo_name):
self.local_logo = logo_name
def drink(self):
print('Energy!')
coke = CocaCola('可口可乐')
print(coke.local_logo)
可口可乐
类的继承
# 按照最新的可口可乐配方来定义这个类
class CocaCola: # 在不继承时,后面对这个括号可写可不写,效果一样
calories = 140
sodium = 45
total_carb = 39
caffeine = 34
ingredients = [
'High Fructose Corn Syrup',
'Carbonated Water',
'Phosphoric Acid',
'Natural Flavors',
'Caramel Color',
'Caffine'
]
def __init__(self, logo_name):
self.local_logo = logo_name
def drink(self):
print('You got {} cal energy!'.format(self.calories))
coke_a = CocaCola('Cocacola')
print(coke_a.local_logo)
coke_a.drink()
Cocacola
You got 140 cal energy!
由于不同的本地化策略和新种类的开发,是的可口可乐生产的包装,容积,甚至配方都会发生变化,但唯一不变的是,它们一直都是可口可乐。所有子品类都会继承可口可乐品牌,在
python
中类的对应概念叫做类的继承
# 小例子之无咖可乐
class CaffeineFree(CocaCola):
calories = 0
ingredients = [
'High Fructose Corn Syrup',
'Carbonated Water',
'Phosphoric Acid',
'Natural Flavors',
'Caramel Color'
]
def __init__(self, logo_name):
self.local_logo = logo_name
def drink(self):
print('You got {} cal energy!'.format(self.calories))
coke_b = CaffeineFree('Cocacola-FREE')
print(coke_b.local_logo)
coke_b.drink()
Cocacola-FREE
You got 0 cal energy!
可以看出:在CaffeineFree后的括号中写入CocaCola表示CaffeineFree这个子类继承CocaCola这个父类,父类中的变量和方法完全被子类继承,如有特殊改动,也会进行覆盖。
令人困惑的类属性和实例属性
Q1:如果类属性被重新赋值,是否会影响到类属性的引用? A1;会
class TestA:
attr = 1
obj_a = TestA()
TestA.attr = 42
print(obj_a.attr)
42
Q2:实例属性如果被重新赋值,是否会影响到类属性的引用? A1:不会
class TestA:
attr = 1
obj_a = TestA()
obj_b = TestA()
obj_a.attr = 42
print(obj_b.attr)
1
Q3:如果类属性和实例属性具有相同名称,那么.
后面引用的将会是什么? A1:类属性
class TestA:
attr = 1 # 类属性
def __init__(self):
self.attr = 42 # 实例属性
obj_a = TestA()
print(obj_b.attr)
1
解释:
类的拓展理解
obj1 = 1
obj2 = 'String!'
obj3 = []
obj4 = {}
print(type(obj1), type(obj2), type(obj3), type(obj4))
<class 'int'> <class 'str'> <class 'list'> <class 'dict'>
python
中任何种类的对象都是类的实例,上面这些类型被称为内建类型,它们不需要实例化。
from bs4 import BeautifulSoup
soup = BeautifulSoup
print(type(soup))
<class 'type'>
- 类的实践没有文档,暂时不实现,理解看懂。