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对于的类
View Code

 

类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 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实例添加nameage属性。

为了达到限制的目的,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
View Code

 

以上是关于Python 面向对象编程的主要内容,如果未能解决你的问题,请参考以下文章

面向面试编程代码片段之GC

面向对象编程其实很简单--python面向对象(初级篇)

Python基础-第六天-面向对象编程

面向对象编程其实很简单——Python 面向对象(初级篇)

python之面向对象编程一

python基础之面向对象