在学习python面向对象的时候,确保自己对python基础已经有所掌握,包括python安装使用,python基本数据类型,python逻辑结构,python函数的使用等。
1.第一个例子,创建类
import sys
class Person(object):
pass
if __name__ == '__main__':
xiaoming = Person()
xiaohong = Person()
print xiaoming
print xiaohong
print xiaoming == xiaohong
上面的例子创建了一个Person类,实例化了两个对象,并打印它们的先关信息。
2.创建实例属性
class Person(object):
pass
p1 = Person()
p1.name = 'Bart'
p2 = Person()
p2.name = 'Adam'
p3 = Person()
p3.name = 'Lisa'
L1 = [p1, p2, p3]
#排序,sort()方法会改变list,可以使用key指定排序参数
#lambda A:B A为参数,B为返回,使用中x表示的是list中的元素
L2 = sorted(L1,key=lambda x:x.name)
print L2[0].name
print L2[1].name
print L2[2].name
实例化了三个对象,并创建了name属性,并进行了排序的操作。
3.python中初始化实例属性
class Person(object):
def __init__(self,name,sex,birth,**kwargs):
self.name = name
self.sex = sex
self.birth = birth
for k,v in kwargs.items():
setattr(self,k,v)
#可变参数**kwargs当成字典来处理,*args直接for i in args
xiaoming = Person('Xiao Ming', 'Male', '1990-1-1', job='Student')
print xiaoming.name
print xiaoming.job
初始化示例的属性,必须定义构造函数init函数,它的第一个参数必须是self表示本对象,使用的时候,直接使用类名类似函数的调用,可以传入不定数量的参数。
4.python中访问限制
class Person(object):
def __init__(self, name, score):
self.name = name
self.__score = score
p = Person('Bob', 59)
print p.name
print p.__score
有错误,__score成员不能被外部访问。
以__开头命令的属性,是不能被外部访问的,可以在类里面访问,如果你想访问,可以试图在类里面定义一个函数返回此属性值,外部通过这个函数进行访问
5.python中创建类属性
绑定在一个实例上的属性不会影响其他实例,但是,类本身也是一个对象,如果在类上绑定一个属性,则所有实例都可以访问类的属性,并且,所有实例访问的类属性都是同一个!也就是说,实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。
#因为类属性是直接绑定在类上的,所以,访问类属性不需要创建实例,就可以直接访问
#对一个实例调用类的属性也是可以访问的,所有实例都可以访问到它所属的类的属性
class Person(object):
count = 0
def __init__(self,name):
self.name = name
Person.count = Person.count + 1
p1 = Person('Bob')
print p1.count
p2 = Person('Alice')
print p2.count
p3 = Person('Tim')
print p3.count
6.类属性和实例属性名字冲突
# 我们发现,在设置了 p1.address = 'China' 后,p1访问 address 确实变成了 'China',
# 但是,Person.address和p2.address仍然是'Earch',怎么回事?
# 原因是 p1.address = 'China'并没有改变 Person 的 address,而是给 p1这个实例绑定了实例属性address ,
# 对p1来说,它有一个实例属性address(值是'China'),而它所属的类Person也有一个类属性address,所以:
# 访问 p1.address 时,优先查找实例属性,返回'China'。
# 访问 p2.address 时,p2没有实例属性address,但是有类属性address,因此返回'Earth'。
# 可见,当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问
class Person(object):
address = 'Earth'
def __init__(self, name):
self.name = name
p1 = Person('Bob')
p2 = Person('Alice')
print 'Person.address = ' + Person.address
p1.address = 'China'
print 'p1.address = ' + p1.address
print 'Person.address = ' + Person.address
print 'p2.address = ' + p2.address
类属性也可以定义成外部不能直接访问的。
#__count的值会随着对象的创建递增,只是外部访问不到
class Person(object):
__count = 0
def __init__(self, name):
Person.__count = Person.__count + 1
self.name = name
print Person.__count
p1 = Person('Bob')
p2 = Person('Alice')
#print Person.__count
7.python中定义实例方法
一个实例的私有属性就是以__开头的属性,无法被外部访问,那这些属性定义有什么用?
虽然私有属性无法从外部访问,但是,从类的内部是可以访问的。除了可以定义实例的属性外,还可以定义实例的方法。
实例的方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样的:
class Person(object):
def __init__(self, name, score):
self.__name = name
self.__score = score
def get_grade(self):
if self.__score >= 80:
return 'A'
if self.__score >= 60:
return 'B'
return 'C'
p1 = Person('Bob', 90)
p2 = Person('Alice', 65)
p3 = Person('Tim', 48)
print p1.get_grade()
print p2.get_grade()
print p3.get_grade()
8.python中方法也是属性
我们在 class 中定义的实例方法其实也是属性,它实际上是一个函数对象,因为方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用 types.MethodType() 把一个函数变为一个方法.给一个实例动态添加方法并不常见,直接在class中定义要更直观.
import types
def fn_get_grade(self):
if self.score >= 80:
return 'A'
if 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()
p2 = Person('Alice', 65)
#print p2.get_grade()
#ERROR: AttributeError: 'Person' object has no attribute 'get_grade'
#因为p2实例并没有绑定get_grade
由于属性可以是普通的值对象,如 str,int 等,也可以是方法,还可以是函数,大家看看下面代码的运行结果,请想一想 p1.get_grade 为什么是函数而不是方法:
class Person(object):
def __init__(self, name, score):
self.name = name
self.score = score
self.get_grade = lambda: 'A'
p1 = Person('Bob', 90)
print p1.get_grade
print p1.get_grade()
直接把 lambda 函数赋值给 self.get_grade 和绑定方法有所不同,函数调用不需要传入 self,但是方法调用需要传入 self。
9.python中定义类方法
和属性类似,方法也分实例方法和类方法。
在class中定义的全部是实例方法,实例方法第一个参数 self 是实例本身。
要在class中定义类方法,需要这么写:
class Person(object):
count = 0
@classmethod
def how_many(cls):
return cls.count
def __init__(self, name):
self.name = name
Person.count = Person.count + 1
print Person.how_many()
p1 = Person('Bob')
print Person.how_many()
通过标记一个 @classmethod,该方法将绑定到 Person 类上,而非类的实例。类方法的第一个参数将传入类本身,通常将参数名命名为 cls,上面的 cls.count 实际上相当于 Person.count。
因为是在类上调用,而非实例上调用,因此类方法无法获得任何实例变量,只能获得类的引用。
#没有问题,通过方法获取私有类属性值
class Person(object):
__count = 0
@classmethod
def how_many(cls):
return cls.__count
def __init__(self, name):
self.name = name
Person.__count = Person.__count + 1
print Person.how_many()
p1 = Person('Bob')
print Person.how_many()
网友评论