@classmethod 修饰的函数在类中执行,不在实例中运行。
@staticmethod 静态方法:处理一些 跟类有关系但在运行时又不需要实例和类参与的功能。
python 类
1.定义:
例:
class Bird(object):
have_feather = True
reproduction = 'oviparous'
def greet(self): ## self代表了一个对象,对象拥有类的所有性质
return "hello"
object:说明这个类没有父类
have_feather、reproduction:是类的属性
greet:是类的方法
2.类的引用:
类的引用方式有两种,属性引用和实例化,以下对比来看。
1)简介:
if __name__ == "__main__":
## 属性引用
f = Bird.have_feather
print f
ret = Bird().greet()
print ret
## 类的实例化
sparrow = Bird()
print sparrow.have_feather
print sparrow.greet()
输出:
True
hello
True
hello
2)对比
if __name__ == "__main__":
print Bird.have_feather #True
## 属性引用
## 改变类中的属性的值,类中的属性值改变,类改变后再创建的实例--->实例的属性也是改变后的。
Bird.have_feather = False
print Bird.have_feather #False
bird = Bird()
print bird.have_feather #False
Bird.have_feather = True
## 类的实例化
## 对实例中的属性进行操作,不影响类的属性,也不会影响其他实例中该属性的值。
bird.have_feather = Fales
print bird.have_feather #False
print Bird.have_feather #True
bird2 = Bird()
print bird2.have_feather #True
输出:
True
False
False
False
True
True
3)创建有初始状态的类 init
class Bird(object):
def __init__(self,extend={'can_run':False,'direction':'N','distance':0}):
self.extend = extend
self.can_run = extend['can_run']
self.direction = extend['direction']
self.distance = extend.get('distance')
can_fly = True
run_distance = 0
run_direction = ''
have_feather = True
reproduction = 'oviparous'
def run(self,others=0): ## 这里run方法还有一个外部参数others,默认值为0
can_run = self.can_run
if can_run is True:
self.run_direction = self.direction
self.run_distance += self.distance+others
print "can"
else:
self.run_direction = 'stop'
self.run_distance += 0
print "cann't"
def get_run_info(self):
return self.run_direction,self.run_distance
创建具有初始状态的类可以通过init方法来实现,类的实例化操作,将会为新建的
类的实例自动调用init方法。
以上,Bird类中run方法每次调用都会修改对象的run_distance、run_direction两个属性。
这里的对象其实可以看做是类的一个实例。
if __name__ == "__main__":
extend = {'can_run':True,'direction':'N','distance':5}
## 用类的实例
sparrow = Bird(extend)
sparrow.run() ## run方法让sparrow实例的属性run_distance 、run_direction发生了变化
print sparrow.get_run_info()
## 用属性引用的方式调
Bird(extend).run(-10) ## 这样会有问题,因为run方法是通过self让对象的属性改变,但这里没有定义对象。×
print Bird().get_run_info() ## ×
输出:
can
(‘N’,5)
can
(”, 0)
3.类的继承-子类
1) 派生类(子类)必须与基类(父类)在同一作用域。
例:
定义一个类Chicken继承Bird类,没有初始化。
定义一个类Ostrich集成Bird类,有初始化。
class Chicken(Bird):
can_fly = False ## 对Bird 类的属性进行了改写
def cook(self,mod=''):
return "delicious {} chicker".format(mod)
## Chicken 子类没有__init__ 则仍通过父类Bird()的__init__初始化
## Ostrich 子类有 __init__ 会通过Ostrich()类的__init__初始化,而不是Bird父类。
## 所以如果父类对象的属性会被使用需要在子类中重新定义一遍。
class Ostrich(Bird):
def __init__(self,extend={'food':'rice'}):
self.extend = extend
self.food = extend['food']
self.can_run = extend['can_run'] ## 如果还要使用父类的属性,或
self.direction = extend['direction'] ## 使用父类的方法时,父类的属性在
self.distance = extend.get('distance') ## 父类的方法中被使用。都需要在init
## 中,接收进self定义
def eat(self):
self.food=self.extend['food']
def get_eat_info(self):
return self.food
创建一个Chicken类的实例,它将可以获得Bird类的属性和方法。
if __name__ == "__main__":
sparrow = Chicken()
print sparrow.can_fly ## 子类中重新定义了父类的属性
print sparrow.have_feather ## 子类继承父类中的属性
print sparrow.reproduction
sparrow.run() ## 子类中继承的父类中的方法
print sparrow.get_run_info()
extend = {'food':'grass','can_run':True,'direction':'N','distance':5}
sparrow2 = Chicken(extend)
sparrow2.run()
print sparrow2.get_run_info()
print "--------------------------"
extend = {'food':'grass','can_run':True,'direction':'N','distance':5}
ostrich = Ostrich(extend)
ostrich.eat() ## 子类自己的方法
print ostrich.get_eat_info()
print ostrich.reproduction ##reproduction是Ostrich父类Bird中的属性
ostrich.run() ## run()Ostrich 父类Bird中的方法。
print ostrich.get_run_info()
输出:
False
True
oviparous
cann’t
(‘stop’, 0)
can
(‘N’, 5)
grass
oviparous
can
(‘N’, 5)
2)多继承-不建议轻易使用
解析类属性的规则:深度优先,从左到右
class A(object):
def __init__(self):
print "I'm A"
ab = 'a'
class B(object):
def __init__(self):
print "I'm B"
ab = 'b'
class A2(A):
def __init__(self):
print "I'm A2"
a2 = 'a2'
if __name__ == "__main__":
c = C()
print c.ab
## A B都有ab属性,C(A,B)
I'm A
a
## A B都有ab属性,C(B,A)
I'm B
b
## A B都有ab属性 ,A2(A),C(B,A,A2)
## 无法建立一致的方法解析 ×
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution
order (MRO) for bases B, A, A2
## A B都有ab属性 ,A2(A),C(B,A2,A)
I'm B
b
4.补充:self的用法
上面,在People类的eat方法中,可以通过self.food的方式调用该类的属性food,
同样,通过self.eat()、self.get_eat_info()的方式也可以调用该类中的方法。
class People(Bird):
def __init__(self,extend):
self.extend = extend
food = ''
def eat(self):
self.food=self.extend['food']
def get_eat_info(self):
return self.food
def three_meals(self):
for times in range(3):
self.eat()
print self.get_eat_info()
if __name__ == "__main__":
extend = {'food':'rice'}
xiaoming = People(extend)
xiaoming.three_meals()
输出:
rice
rice
rice
self其实是类的实例在类内部的表示,也就是说在eat方法中self.food=…其实是对实例中
的属性进行了修改。用一段代码解释一下:
if __name__ == "__main__":
extend = {'food':'rice'}
xiaoming = People(extend)
xiaoming.eat()
print xiaoming.get_eat_info() ## rice
print xiaoming.food ## rice
输出:
rice
rice