文章目录
7.1 class语句
类通常包含:
- 方法
method
- 类变量
class variable
- 属性
property
注意类变量与属性的区别,类变量类似java的静态变量,它在所有实例中共享值。
class Account(object):
num_accounts=0 //类变量
def __init__(self,name):
self.name=name //属性
Account.num_accounts+=1
def name(self):
return self.name
7.2 类实例
x=Account('Girlbert',30)
name
使用x.name()
时被认为是实例的属性name
,抛出无法调用的错误。x.count
:首先查找实例属性,如果找不到实例的属性,再查找类变量
7.3 作用域规则
Python类特有的一个机制是:实例都包含一个dict
,使用x.anykey=value
可以为实例增加一个属性。
Python不会为方法中用到的名称创建作用域,它的后果是:如果要引用方法以外的属性/方法,必须是完全限定的。
class Foo(object):
def bar(self):
print("bar")
k=10 //k的作用域范围仅仅在方法内部
def spam(self):
bar(self) //ERROR
self.bar() //correct
Foo.bar(self)//correct
7.4 继承
典型的继承类举例:
import t_class.account as account
class Student(account.Account):
def __init__(self,name,age,level):
account.Account.__init__(self,name,age)
self.level=level
继承类的初始化方法中Account.__init__()
语法上不是必须的,这个方法是初始化self
而不是创建父类实例。
调用基类的同名方法:Account.method(self,*args,**kwargs)
,还可以使用super
class Account(object):
def foo(self):
print("account")
class Student(Account):
def foo(self):
print("Student")
class JuniorStudent(Student):
def foo(self):
print("JuniorStudent")
super().foo() //输出Student
此处如果Studnet
没有实现foo()
,super().foo()
那么输出结果将是Account
.这两种调用基类方法的方法各有优点:super
只需要有一个基类实现了方法即可,而Account.method()
能够具体指定使用哪个基类的方法。
7.4.1 多重继承
python支持多重继承。多重继承有一个关键问题:属性解析变得复杂。Python解析属性的优先级大约
是:将所有基类从"最特殊"的类到"最不特殊"的类。或者将继承图列成一个树:
0 1 2
/ \
0.1.1 0.1.2
/
0.2
它的优先级即:2 -> 1.2 -> 1.2 -> 0 -> 1 -> 2
对于同层级的类,优先级是按照定义时参数的顺序来的。
基类的准确顺序由C3线性化
算法确定。使用tudent.__mro__
可以查看属性解析顺序。
class X(object):pass
class Y(X):pass
class (X,Y):pass #TypeError:不能确定方法解析顺序
它不能解析的原因是:Y比X更特殊,却出现在后面。
虽然python支持多重继承,但最好不要使用多重继承,特别是在解析顺序不直观的情况下。多重继承可以用于定义混合类
,被混合的类最好没有关联。
obj.attr
的顺序:实例本身>实例的类>基类
7.5 多态动态绑定和鸭子类型
动态绑定
:不考虑实例类型的情况下使用实例。
例如obj.name()
:对于所有拥有