☆面向对象
定义类&创建实例:
class Person:
pass
xiaoming = Person()
创建实例属性:
如上,先创建实例,再创建实例。动态语言嘛,与js
相似
xiaoming.school = ‘CUIT’
xiaoming.age = 20
xiaoming.age = xiaoming.age + 1
初始化实例属性:
在定义Person类时,可以为Person类添加一个特殊的__init__()
方法
class Person(object):
def __init__(self, name, gender, birth):
self.name = name
self.gender = gender
self.birth = birth
在创建实例的时候,就必须提供self
以外的参数
xiaoming = Person(‘XiaoM’, ‘Male’, ‘1991-1-1’)
任务:
Person类除了接收name, gender, birth之外,还可以接收任意关键字参数
class Person(object):
def __init__(self, name, gender, birth, **kw):
self.name = name
self.gender = gender
self.birth = birth
for k,v in kw.iteritems():
setattr(self, k, v)
xiaoming = Person('小明', '男', '1990-1-1', job='student')
print xiaoming.job
==>student
访问限制:
Python对属性权限的控制是通过属性名来控制的
属性名 双下划线 (_ _),该属性就无法被外部访问
class Person(object):
def __init__(self, name):
self.name = name
self._title = 'Mr'
self.__job = 'student'
p = Person('Bob')
print p.name
==>Bob
print p._title
==>Mr
print -.__job
==>AttributeError
可见,只有以__
开头的__job
不能被外部访问
但是,若以_xxx_
形式来定义,就被称为特殊属性,能被外界访问
有很多预定义的特殊属性可以使用,所以,通常不要把普通属性用_xxx_
定义
以单下划线_xx
开头的属性能被外界访问,但是按照习惯,它不应该被访问???
Python创建类属性:
实例属性,各自一份。类属性,共同一份
class Person(object):
address = 'CUIT'
def __init__(self, name):
self.name = name
print Person.address
==>CUIT
p = Person('Bob')
p.address #这样也是可以的,以实例属性访问的方式访问类属性
==>'CUIT'
p.address = 'PKU'
Person.address
==>CUIT
p.address
==>PKU
类实例可以被修改,但是只能以Person.address
的形式去访问他,并修改
实例p.address,可以理解为在实例p上新添加属性address
类属性名与实例属性名冲突:
Person.address = 'CUIT'
p.address = 'PKU'
print p.address
==>PKU
del p.address
print p.address
==>CUIT
可见,当实力属性与类属性重名时,实例属性优先于类属性,将屏蔽掉对类属性的访问
当我们将p的address属性删除后,访问p.address就是实例属性了
定义实例方法:
实例方法就是在类中定义的函数。第一个参数一定是self
,指向实例本身,同Java中的this
class Person(object):
def __init__(self, name):
self.name = name
def get_name(self):
return self.name
#调用
p = Person('Bob')
print p.get_name() #self不需要显示地传入
==>Bob
在实例方法内部,可以访问所有实例属性。
这样,如果外部要访问 私有属性 可以通过方法调用
好处:数据封装,保护数据一致性,简化外部调用
方法也是属性:
我们在class中定义的实例方法也是属性,它实际上是一个函数对象
print p.get_name
==><Object......> #返回一个函数对象
但这个函数是一个绑定到实例的函数
因为方法也是属性,所以呢,它可以被动态地添加到实例上,只是需要types.MethodType()
把一个函数转变为方法
import types
def fn_get_grade(self):
if self.score >= 80:
return 'A'
elif self.score >= 60:
return 'B'
return 'C'
class Person(object):
def __init__(self, name, score):
self.name = name
self.score = score
p1 = Person('Bob', 90)
p1.get_grade = types.MethodType(fn_get_grade, p1, Person)
print p1.get_grade()
==>A
p2 = Person('Alice', 65)
print p2.get_grade()
==>AttributeError
#因为p2没有绑定get_grade
#给一个实例动态添加方法并不常见,直接在class中定义更为直观
#函数与方法的表面区别就是:有没有参数`self`
Python中定义类的方法:
和属性类似,方法也分为实例方法和类方法
在class中定义的方法都是实例方法,实例方法的第一个参数self是实例本身。
在class中定义类方法,需要这么写:
class Person(object):
count = 0
@classmethod
def how_many(cls):
return cls.count
通常通过@classmethod来标识该方法绑定到Person类上,而非类的实例
类方法的第一个参数将传入类本身
通常将参数命名为cls
上面的cls.count相当于Person.count
因为类方法在实例上调用,因此,无法获取任何实例属性,只能获取类的引用