Python 面向对象编程
Posted 北风吹沙
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 面向对象编程相关的知识,希望对你有一定的参考价值。
1.类和实例
对于Python,声明与定义类没什么区别,同时进行。定义(类体)紧跟在声明(含class的头行)和可选的文档字符串后面
1 #!/usr/bin/python3 2 3 class Student(object): 4 #表示该类从哪个类继承下来的,如没有合适的继承类,就是用object类 5 #这是所有类最终都会继承的类 6 def __init__(self,name,score): 7 self.name = name 8 self.score = score 9 def print_score(self): 10 print(\'%s:%s\' % (self.name, self.score)) 11 12 b = Student(\'Chb\', 100) #创建实例 13 print(b.name) 14 print(b.score) 15 print(b.print_score())
如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__
,在Python中,实例的变量名如果以__
开头,就变成了一个私有变量(private),只有在类的内部可以访问,外部不能访问
类有一个名为 __init__() 的特殊方法(构造方法),该方法在类实例化时会自动调用,重写__init__不会自动调用基类的__init__,如想调用基类的__init__():
1 class C(P): 2 def __init__(self): 3 P.__init__(self) 4 print("....")
任何类都有的特殊属性():
1 A.__name__ #类A的名字 特殊属性都是两个下划线开头 2 A.__doc__ #类A的文档字符串 3 A.__bases__ #类A的所有父类构成的元组 4 A.__dict__ #类A的属性 5 A.__module__#类A定义所在模块 6 A.__class__ #实例A对于的类
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self
self代表类的实例,而非类,表示创建的实例本身
实例绑定的数据属性属于实例对象,类数据属性(即静态数据类型)是属于类的
1 class C(object): 2 foo = 100 3 4 print(C.foo) #100 5 B = C() 6 B.foo = C.foo+100 7 print(B.foo) #200 8 print(C.foo) #100
2.获取对象信息
当我们拿到一个对象的引用时,如何知道这个对象是什么类型、有哪些方法呢?
使用type()
返回对应的class类型
使用isinstance(obj1,obj2)
布尔函数判断一个对象是否是另一个给定类的实例
使用issubclass(sub,sup)
布尔函数判断一个类是另一个类的子类或子孙类
使用dir()
如果要获得一个对象的所有属性和方法,可以使用dir()
函数,它返回一个包含字符串的list
__slots__ 限制实例的属性
在Python中,定义一个class类并创建了一个class的实例后,可以给该实例绑定任何属性和方法,这是动态语言的灵活性
但是,给一个实例绑定的方法,对另一个实例是不起作用的
如果我们想要限制实例的属性怎么办?比如,只允许对Student实例添加name
和age
属性。
为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__
变量,来限制该class实例能添加的属性
由于\'score\'
没有被放到__slots__
中,所以不能绑定score
属性,试图绑定score
将得到AttributeError
的错误。
使用__slots__
要注意,__slots__
定义的属性仅对当前类实例起作用,对继承的子类是不起作用的
@property
@property
广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查。把一个方法变成属性调用
1 #!/usr/bin/python3 2 3 class Student(object): 4 @property 5 def score(self): 6 return self._score 7 @score.setter 8 def score(self, value): 9 if not isinstance(value, int): 10 raise ValueError(\'分数必须是整数\') 11 if value<0 or value>100: 12 raise ValueError(\'分数必需在0~100之间\') 13 self._score = value 14 15 s = Student() 16 s.score = 60 17 print(s.score) 18 print(\'------------------------------\') 19 s.score = 999 20 print(s.score)
3.多重继承
给一个类增加多个功能,多继承时,若是基类中有相同的方法名,而在子类使用时未指定,Python从左至右搜索
class Dog(A, B, C): pass
4.定制类
非常方便生成特定的类
__str__
打印自定义的实例
1 #!/usr/bin/python3 2 3 class Student(object): 4 def __init__(self, name): 5 self.name = name 6 def __str__(self): 7 return \'Student object (name:%s)\' % self.name 8 __repe__ = __str__ 9 10 s = Student(\'Chb\') 11 print(s)
__iter__
如果一个类想被用于for ... in
循环,类似list或tuple那样,就必须实现一个__iter__()
方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的__next__()
方法拿到循环的下一个值,直到遇到StopIteration
错误时退出循环。
1 #!/usr/bin/python3 2 3 class Fib(object): 4 def __init__(self): 5 self.a, self.b = 1,1 6 def __iter__(self): 7 return self #实例本身就是迭代对象,故返自己 8 def __next__(self): 9 self.a, self.b = self.b, self.a+self.b 10 if self.a > 1000: #退出循环条件 11 raise StopIteration() 12 return self.a 13 14 for n in Fib(): 15 print(n)
__getitem__
使自己定义的类型和list、dict没什么区别,如可以按索引取值、切片
1 #!/usr/bin/python3 2 3 class Fib(object): 4 def __getitem__(self, n): 5 if isinstance(n, int): #n是索引的情况 6 a, b = 1, 1 7 for x in range(n): 8 a, b = b, a+b 9 return a 10 if isinstance(n, slice): #n是切片的情况 11 start = n.start 12 stop = n.stop 13 if start is None: #如果开头没赋值 L[::] 则默认开始下标为0 14 start = 0 15 a, b = 1, 1 16 L = [] 17 for x in range(stop): 18 if x >= start: 19 L.append(a) 20 a, b = b, a+b 21 return L 22 23 f = Fib() 24 print(f[10]) 25 print(f[0:5])
__getattr__
正常情况下,当我们调用类的方法或属性时,如果不存在,就会报错。
要避免这个错误,可以写一个__getattr__()
方法,动态返回一个属性。
1 #!/usr/bin/python3 2 3 class Student(object): 4 def __init__(self): 5 self.name = \'aaa\' 6 def __getattr__(self, attr): 7 if attr == \'score\': 8 return 60 9 10 s = Student() 11 print(s.name) 12 print(s.score)
当调用不存在的属性时,比如score
,Python解释器会试图调用__getattr__(self, \'score\')
来尝试获得属性,这样,我们就有机会返回score
的值
__call__
直接对实例进行调用
1 #!/usr/bin/python3 2 3 class Student(object): 4 def __init__(self, name): 5 self.name = name 6 def __call__(self): 7 print(\'My name is %s\' % self.name) 8 9 s = Student(\'chb\') 10 print(s())
6.实例方法、类方法、静态方法
实例方法:类实例化后才能调用,参数的值不能调用类属性
类方法:只能调用类属性,类和实例都能调用它
1 @classmethod 2 def classget(cls): 3 print(cls.x)
静态方法:类对象和实例都可以调用的静态方法
1 @staticmethod 2 def add(a,b): 3 return a+b
1 class A(): 2 3 x = 100 4 @classmethod 5 def classget(A): 6 print(A.x) 7 8 @staticmethod 9 def add(a,b): 10 return a+b 11 12 if __name__==\'__main__\': 13 a = A() 14 A.classget() #100 15 a.classget() #100 16 sum1 = a.add(2,3) 17 sum2 = A.add(2,5) 18 print(sum1,sum2) #5 7
以上是关于Python 面向对象编程的主要内容,如果未能解决你的问题,请参考以下文章