一、对象的继承
Python中支持一个类同时继承多个父类
1
2
3
4
5
6
7
8
9
10
|
class Parent1: pass class Parent2: pass class Sub1(Parent1, Parent2): pass |
使用__bases__方法可以获取对象继承的类
1
2
|
print (Sub1.__bases__) # (<class '__main__.Parent1'>, <class '__main__.Parent2'>) |
在Python3中如果一个类没有继承任何类,则默认继承object类。
1
2
|
print (Parent1.__bases__) #('object'>,) |
1、类的构造函数继承__init__():
- 子类需要自动调用父类的方法:子类不重写__init__()方法,实例化子类后,会自动调用父类的__init__()的方法。
- 子类不需要自动调用父类的方法:子类重写__init__()方法,实例化子类后,将不会自动调用父类的__init__()的方法。
- 子类重写__init__()方法又需要调用父类的方法:需要使用super关键词。
2、继承关系中,对象查找属性的顺序
对象自己——>对象的类——>父类——>父类。。。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
class OldboyPeople: """由于学生和老师都是人,因此人都有姓名、年龄、性别""" school = 'oldboy' def __init__( self , name, age, gender): self .name = name self .age = age self .gender = gender class OldboyStudent(OldboyPeople): def choose_course( self ): print ( '%s is choosing course' % self .name) class OldboyTeacher(OldboyPeople): def score( self , stu_obj, num): print ( '%s is scoring' % self .name) stu_obj.score = num stu1 = OldboyStudent( 'tank' , 18 , 'male' ) tea1 = OldboyTeacher( 'nick' , 18 , 'male' ) print (stu1.school) # oldboy print (tea1.school) # oldboy print (stu1.__dict__) # {'name': 'tank', 'age': 18, 'gender': 'male'} tea1.score(stu1, 99 ) # nick is scoring print (stu1.__dict__) # {'name': 'tank', 'age': 18, 'gender': 'male', 'score': 99} |
二、类的派生
子类中新定义的属性的这个过程叫做派生,子类在使用派生的属性时始终以自己的为准。
1、派生方法一(类调用)
指名道姓访问某一个类的函数:该方式与继承无关
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
class OldboyPeople: """由于学生和老师都是人,因此人都有姓名、年龄、性别""" school = 'oldboy' def __init__( self , name, age, gender): self .name = name self .age = age self .gender = gender class OldboyStudent(OldboyPeople): """由于学生类没有独自的__init__()方法,因此不需要声明继承父类的__init__()方法,会自动继承""" def choose_course( self ): print ( '%s is choosing course' % self .name) class OldboyTeacher(OldboyPeople): """由于老师类有独自的__init__()方法,因此需要声明继承父类的__init__()""" def __init__( self , name, age, gender, level): OldboyPeople.__init__( self , name, age, gender) self .level = level # 派生 def score( self , stu_obj, num): print ( '%s is scoring' % self .name) stu_obj.score = num stu1 = OldboyStudent( 'tank' , 18 , 'male' ) tea1 = OldboyTeacher( 'nick' , 18 , 'male' , 10 ) print (stu1.__dict__) # {'name': 'tank', 'age': 18, 'gender': 'male'} print (tea1.__dict__) # {'name': 'nick', 'age': 18, 'gender': 'male', 'level': 10} |
2、派生方法二(super)
- 严格以继承属性查找关系
- super()会得到一个特殊的对象,该对象就是专门用来访问父类中的属性的(按照继承的关系)
- super().__init__(不用为self传值)
- super的完整用法是super(自己的类名,self),在python2中需要写完整,而python3中可以简写为super()。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
class OldboyPeople: school = 'oldboy' def __init__( self , name, age, sex): self .name = name self .age = age self .sex = sex def choose_course( self ): print ( '%s is choosing course' % self .name) class OldboyStudent(OldboyPeople): def __init__( self , name, age, sex, stu_id): # OldboyPeople.__init__(self,name,age,sex) # super(OldboyStudent, self).__init__(name, age, sex) super ().__init__(name, age, sex) self .stu_id = stu_id def choose_course( self ): print ( '%s is choosing course' % self .name) stu1 = OldboyStudent( 'tank' , 19 , 'male' , 1 ) super (OldboyStudent,stu1).choose_course() #用子类对象调用父类已被覆盖的方法 print (stu1.__dict__) # {'name': 'tank', 'age': 19, 'sex': 'male', 'stu_id': 1} |
三、类的组合
类对象可以引用/当做参数传入/当做返回值/当做容器元素,类似于函数对象。
- 组合是用来解决类与类之间代码冗余的问题
组合可以理解成多个人去造一个机器人,有的人造头、有的人造脚、有的人造手、有的人造躯干,大家都完工后,造躯干的人把头、脚、手拼接到自己的躯干上,因此一个机器人便造出来了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
class Course: def __init__( self , name, period, price): self .name = name self .period = period self .price = price class OldboyPeople: school = 'oldboy' def __init__( self , name, age, sex): self .name = name self .age = age self .sex = sex class OldboyStudent(OldboyPeople): def __init__( self , name, age, sex, stu_id): OldboyPeople.__init__( self , name, age, sex) self .stu_id = stu_id def choose_course( self ): print ( '%s is choosing course' % self .name) class OldboyTeacher(OldboyPeople): def __init__( self , name, age, sex, level): OldboyPeople.__init__( self , name, age, sex) self .level = level def score( self , stu, num): stu.score = num print ( '老师[%s]为学生[%s]打分[%s]' % ( self .name, stu.name, num)) # 创造课程 python = Course( 'python全栈开发' , '5mons' , 3000 ) linux = Course( 'linux运维' , '5mons' , 800 ) # 创造学生与老师 stu1 = OldboyStudent( 'tank' , 19 , 'male' , 1 ) tea1 = OldboyTeacher( 'nick' , 18 , 'male' , 10 ) # 组合 # 将学生、老师与课程对象关联/组合 stu1.course = python tea1.course = linux |
四、多父类继承问题
Python同样有限的支持多继承形式。多继承的类定义形如下例:
1
2
3
4
5
|
class DerivedClassName(Base1, Base2, Base3): . . . |
需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 。即方法在子类中未找到时,从左到右查找父类中是否包含方法。
1、新式类(MRO)列表
- 继承了object的类以及该类的子类,都是新式类
- Python3中所有的类都是新式类
- 广度优先, 老祖宗最后找。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
class G( object ): # def test(self): # print('from G') pass class E(G): # def test(self): # print('from E') pass class B(E): # def test(self): # print('from B') pass class F(G): # def test(self): # print('from F') pass class C(F): # def test(self): # print('from C') pass class D(G): # def test(self): # print('from D') pass class A(B, C, D): def test( self ): print ( 'from A' ) obj = A() obj.test() # A->B->E-C-F-D->G-object # from A |
python计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,来实现继承的。
为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。而这个MRO列表的构造是通过一个C3线性化算法来实现的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
print (A.mro()) # A.__mro__ # [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class '__main__.G'>, <class 'object'>] for i in A.mro(): print (i) # <class '__main__.A'> # <class '__main__.B'> # <class '__main__.E'> # <class '__main__.C'> # <class '__main__.F'> # <class '__main__.D'> # <class '__main__.G'> # <class 'object'> |
2、super()方法详解
super() 函数是用于调用父类(超类)的一个方法。
super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
下面的例子可以看到:
- 每个类开始调用是根据MRO顺序进行开始,然后逐个进行结束的。
- 由于因为需要继承不同的父类,参数不一定,所有的父类都应该加上不定参数*args , **kwargs ,不然参数不对应是会报错的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
# 胖子老板的父类 class FatFather( object ): def __init__( self , name, * args, * * kwargs): print () print ( "=============== 开始调用 FatFather ========================" ) print ( 'FatFather的init开始被调用' ) self .name = name print ( '调用FatFather类的name是%s' % self .name) print ( 'FatFather的init调用结束' ) print () print ( "=============== 结束调用 FatFather ========================" ) # 胖子老板类 继承 FatFather 类 class FatBoss(FatFather): def __init__( self , name, hobby, * args, * * kwargs): print () print ( "=============== 开始调用 FatBoss ========================" ) print ( '胖子老板的类被调用啦!' ) # super().__init__(name) # 因为多继承传递的参数不一致,所以使用不定参数 super ().__init__(name, * args, * * kwargs) print ( "%s 的爱好是 %s" % (name, hobby)) print () print ( "=============== 结束调用 FatBoss ========================" ) # 胖子老板的老婆类 继承 FatFather类 class FatBossWife(FatFather): def __init__( self , name, housework, * args, * * kwargs): print () print ( "=============== 开始调用 FatBossWife ========================" ) print ( '胖子老板的老婆类被调用啦!要学会干家务' ) # super().__init__(name) # 因为多继承传递的参数不一致,所以使用不定参数 super ().__init__(name, * args, * * kwargs) print ( "%s 需要干的家务是 %s" % (name, housework)) print () print ( "=============== 结束调用 FatBossWife ========================" ) # 胖子老板的女儿类 继承 FatBoss FatBossWife类 class FatBossGril(FatBoss, FatBossWife): def __init__( self , name, a, b): print ( '胖子老板的女儿类被调用啦!要学会干家务,还要会帮胖子老板斗地主' ) super ().__init__(name, a, b) def main(): print ( "打印FatBossGril类的MRO" ) print (FatBossGril.__mro__) # (<class '__main__.FatBossGril'>, <class '__main__.FatBoss'>, <class '__main__.FatBossWife'>, <class '__main__.FatFather'>, <class 'object'>) print ( "=========== 下面按照 MRO 顺序执行super方法 =============" ) gril = FatBossGril( "胖子老板" , "打斗地主" , "拖地" ) if __name__ = = "__main__" : main() # =========== 下面按照 MRO 顺序执行super方法 ============= # 胖子老板的女儿类被调用啦!要学会干家务,还要会帮胖子老板斗地主 # # =============== 开始调用 FatBoss ======================== # 胖子老板的类被调用啦! # # =============== 开始调用 FatBossWife ======================== # 胖子老板的老婆类被调用啦!要学会干家务 # # =============== 开始调用 FatFather ======================== # FatFather的init开始被调用 # 调用FatFather类的name是胖子老板 # FatFather的init调用结束 # # =============== 结束调用 FatFather ======================== # 胖子老板 需要干的家务是 拖地 # # =============== 结束调用 FatBossWife ======================== # 胖子老板 的爱好是 打斗地主 # # =============== 结束调用 FatBoss ======================== |
五、抽象类
多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
import abc class Animal(metaclass = abc.ABCMeta): # 同一类事物:动物 @abc .abstractmethod # 上述代码子类是约定俗称的实现这个方法,加上@abc.abstractmethod装饰器后严格控制子类必须实现这个方法 def talk( self ): raise AttributeError( '子类必须实现这个方法' ) class People(Animal): # 动物的形态之一:人 def talk( self ): print ( 'say hello' ) class Dog(Animal): # 动物的形态之二:狗 def talk( self ): print ( 'say wangwang' ) class Pig(Animal): # 动物的形态之三:猪 def talk( self ): print ( 'say aoao' ) peo2 = People() pig2 = Pig() d2 = Dog() peo2.talk() pig2.talk() d2.talk() # say hello # say aoao # say wangwang |
六、类的封装
类中把某些属性和方法隐藏起来(或者说定义成私有的),只在类的内部使用、外部无法访问,或者留下少量接口(函数)供外部访问。
1、私有属性:双下划线的方式__x
在python中用双下划线的方式__x实现隐藏属性(设置成私有的),我们需要在类中定义一个函数(接口函数)在它内部访问被隐藏的属性,然后外部就可以使用了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
class Site: def __init__( self , name, url): self .name = name # public self .__url = url # private def who( self ): print ( 'name : ' , self .name) print ( 'url : ' , self .__url) def __foo( self ): # 私有方法 print ( '这是私有方法' ) def foo( self ): # 公共方法 print ( '这是公共方法' ) self .__foo() x = Site( '菜鸟教程' , 'www.runoob.com' ) x.who() # 正常输出 x.foo() # 正常输出 x.__foo() # 报错 |
2、外部使用变形访问:_类名__x
类中所有双下划线开头的名称如__x都会自动变形成: _类名__x的形式:
这种自动变形的特点:
- 类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果。
- 这种变形其实正是针对内部的变形,在外部是无法通过__x这个名字访问到的。
- 在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。
这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
class A: __N = 0 # 把类的数据属性设置成私有的如__N,会变形为_A__N def __init__( self ): self .__X = 10 # 变形为self._A__X def __foo( self ): # 变形为_A__foo print ( 'from A' ) def bar( self ): self .__foo() # 只有在类内部才可以通过__foo的形式访问到. # 对象测试 a = A() print (a._A__N) # 0 print (a._A__X) # 10 # 类测试 print (A._A__N) # 0 print (A._A__X) # 对象私有的属性# type object 'A' has no attribute '_A__X' |
注意:变形的过程只在类的定义时发生一次,在定义后的赋值操作,不会变形。
1
2
3
4
5
|
a = A() print (a.__dict__) # {'_A__X': 10} a.__Y = 1 print (a.__dict__) # {'_A__X': 10, '__Y': 1} |
3、在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
# 正常情况 class A: def fa( self ): print ( 'from A' ) def test( self ): self .fa() class B(A): def fa( self ): print ( 'from B' ) b = B() b.test() # from B # 把fa定义成私有的,即__fa class A: def __fa( self ): # 在定义时就变形为_A__fa print ( 'from A' ) def test( self ): self .__fa() # 只会与自己所在的类为准,即调用_A__fa class B(A): def __fa( self ): #子类无法覆盖 print ( 'from B' ) b = B() b.test() # from A |
python模块也遵循这种约定,如果模块中的变量名_amodule以单下划线开头,那么from module import *时不能被导入该变量,但是你from module import_amodule依然是可以导入该变量的。
如果遇到下划线开头的(socket._socket,sys._home,sys._clear_type_cache),这些都是私有的,原则上是供内部调用的,作为外部也是可以用的。严格控制属性的访问权限,只能借助内置方法如__getattr__。
七、类的属性(property)
1、装饰器方式 (推荐使用)
property装饰器用于将被装饰的方法伪装成一个数据属性,在使用时可以不用加括号而直接使用。
- 1. 定义时,在实例方法的基础上添加 @property 装饰器,并且仅有一个self参数
- 2. 调用时,无需括号
property属性的功能是:property属性内部进行一系列的逻辑计算,最终将计算结果返回。
分页的功能包括:
- 根据用户请求的当前页和总数据条数计算出 m 和 n
- 根据m 和 n 去数据库中请求数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
class Pager: def __init__( self , current_page): # 用户当前请求的页码(第一页、第二页...) self .current_page = current_page # 每页默认显示10条数据 self .per_items = 10 @property def start( self ): val = ( self .current_page - 1 ) * self .per_items return val @property def end( self ): val = self .current_page * self .per_items return val # ############### 调用 ############### p = Pager( 2 ) print (p.start) # 就是起始值,即:m # 10 print (p.end) # 就是结束值,即:n # 20 |
2、经典类和新式类的属性方式:
-
经典类中的属性只有一种访问方式,其对应被 @property 修饰的方法。
-
新式类(如果类继object,那么该类是新式类 )中的属性有三种访问方式,并分别对应了三个被 @property、@方法名.setter、@方法名.deleter 修饰的方法,对同一个属性:获取、修改、删除
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
class Goods( object ): def __init__( self ): # 原价 self .original_price = 100 # 折扣 self .discount = 0.8 @property def price( self ): # 实际价格 = 原价 * 折扣 new_price = self .original_price * self .discount return new_price @price .setter def price( self , value): self .original_price = value @price .deleter def price( self ): print ( 'del' ) del self .original_price obj = Goods() print (obj.price) # 获取商品价格 # 80.0 obj.price = 200 # 修改商品原价 print (obj.price) # 160.0 del obj.price # 删除商品原价 # del |
3、类属性方式
注意:当使用类属性的方式创建property属性时,经典类和新式类无区别。
property方法中有个四个参数
- 第一个参数是调用 对象.属性 时自动触发执行方法
- 第二个参数是调用 对象.属性 = XXX 时自动触发执行方法
- 第三个参数是调用 del 对象.属性 时自动触发执行方法
- 第四个参数是字符串,调用 对象.属性.__doc__ ,此参数是该属性的描述信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
class Goods( object ): def __init__( self ): # 原价 self .original_price = 100 # 折扣 self .discount = 0.8 def get_price( self ): # 实际价格 = 原价 * 折扣 new_price = self .original_price * self .discount return new_price def set_price( self , value): self .original_price = value def del_price( self ): del self .original_price PRICE = property (get_price, set_price, del_price, '价格属性描述...' ) obj = Goods() print (obj.PRICE) # 获取商品价格 # 80.0 obj.PRICE = 200 # 修改商品原价 print (obj.PRICE) # 160.0 del obj.PRICE # 删除商品原价 |
3、实例
实现一个属性的设置和读取方法,可做边界判定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
class Money( object ): def __init__( self ): self .__money = 0 # 使用装饰器对money进行装饰,那么会自动添加一个叫money的属性,当调用获取money的值时,调用装饰的方法 @property def money( self ): return self .__money # 使用装饰器对money进行装饰,当对money设置值时,调用装饰的方法 @money .setter def money( self , value): if isinstance (value, int ): self .__money = value else : print ( "error:不是整型数字" ) a = Money() a.money = 100 print (a.money) # 100 |
八、实例方法及非绑定实例方法
1、实例方法
在类中没有被任何装饰器修饰的方法就是绑定到对象的实例方法,这类方法专门为对象定制。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class Person: country = "China" def __init__( self , name, age): self .name = name self .age = age def speak( self ): print ( self .name + ', ' + str ( self .age)) p = Person( 'Kitty' , 18 ) print (p.__dict__) # {'name': 'Kitty', 'age': 18} print (Person.__dict__[ 'speak' ]) # |
speak即为绑定到对象的方法,这个方法不在对象的名称空间中,而是在类的名称空间中。
绑定到对象的方法:
- 通过对象调用,会有一个自动传值的过程,即自动将当前对象传递给方法的第一个参数(self,一般都叫self,也可以写成别的名称);
- 使用类调用,则第一个参数需要手动传值。
1
2
3
4
5
6
|
p = Person( 'Kitty' , 18 ) p.speak() # 通过对象调用 # Kitty, 18 Person.speak(p) # 通过类调用 # Kitty, 18 |
2、类方法(@classmethod )
类中使用 @classmethod 修饰的方法就是绑定到类的方法。这类方法专门为类定制。
- 通过类名调用绑定到类的方法时,会将类本身当做参数传给类方法的第一个参数。类方法默认有个 cls 参数。
- 通过对象也可以调用,只是默认传递的第一个参数还是这个对象对应的类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
class Operate_database(): host = '192.168.0.5' port = '3306' user = 'abc' password = '123456' @classmethod def connect( cls ): # 约定俗成第一个参数名为cls,也可以定义为其他参数名 print ( cls ) print ( cls .host + ':' + cls .port + ' ' + cls .user + '/' + cls .password) Operate_database.connect() # <class '__main__.Operate_database'> # 192.168.0.5:3306 abc/123456 Operate_database().connect() # 输出结果一致 # <class '__main__.Operate_database'> # 192.168.0.5:3306 abc/123456 |
3、静态方法(@staticmethod )
在类内部使用 @staticmethod 修饰的方法即为非绑定的静态方法,这类方法和普通定义的函数没有区别,不与类或对象绑定,谁都可以调用,且没有自动传值的效果。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
import hashlib class Operate_database(): def __init__( self , host, port, user, password): self .host = host self .port = port self .user = user self .password = password @staticmethod def get_passwrod(salt, password): m = hashlib.md5(salt.encode( 'utf-8' )) # 加盐处理 m.update(password.encode( 'utf-8' )) return m.hexdigest() hash_password = Operate_database.get_passwrod( 'lala' , '123456' ) # 通过类来调用 print (hash_password) # f7a1cc409ed6f51058c2b4a94a7e1956 p = Operate_database( '192.168.0.5' , '3306' , 'abc' , '123456' ) hash_password = p.get_passwrod(p.user, p.password) # 也可以通过对象调用 print (hash_password) # 0659c7992e268962384eb17fafe88364 |
九、类的专有方法:
- __init__ : 构造函数,在生成对象时调用
- __del__ : 析构函数,释放对象时使用
- __repr__ : 打印,转换
- __setitem__ : 按照索引赋值
- __getitem__: 按照索引获取值
- __len__: 获得长度
- __cmp__: 比较运算
- __call__: 函数调用
- __name__:模块名称,一段程序作为主线运行程序时其内置名称就是 __main__
运算符重载
- __add__: 加运算
- __sub__: 减运算
- __mul__: 乘运算
- __truediv__: 除运算
- __mod__: 求余运算
- __pow__: 乘方
对类的专有方法进行重载实例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class Vector: def __init__( self , a, b): self .a = a self .b = b def __str__( self ): return 'Vector (%d, %d)' % ( self .a, self .b) def __add__( self ,other): return Vector( self .a + other.a, self .b + other.b) v1 = Vector( 2 , 10 ) v2 = Vector( 5 , - 2 ) print (v1 + v2) #Vector(7,8) |
到此这篇关于Python面向对象编程的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://www.cnblogs.com/springsnow/p/11985145.html