python类相关
python 绑定到对象的方法
1 class Foo: 2 school=0 3 def __init__(self,name,age,sex): 4 self.name=name 5 self.age=age 6 self.sex=sex 7 Foo.school+=1 8 def learn(self): 9 print('%s is learning' %self.name) #新增self.name 10 11 def eat(self): 12 print('%s is eating' %self.name) 13 14 def sleep(self): 15 print('%s is sleeping' %self.name) 16 17 f1=Foo('lit1',18,'Male') 18 f2=Foo('lit2',19,'Male') 19 f3=Foo('lit3',20,'FeMale') 20 21 f1.learn() 22 f2.eat() 23 f3.sleep()
类中定义的函数(没有被任何装饰器装饰的),其实主要是给对象使用的,而且是绑定到对象的,虽然所有对象指向的都是相同的功能,但是绑定到不同的对象就是不同的绑定方法,就是带self的那些函数,把自身当做参数传入。
类本身也是可以调用这些函数的,但必须传入一个实例化的对象,当做self。
1 2 3 | Foo.learn(f1) Foo.sleep(f2) Foo.eat(f3) |
对象之间的交互
1 class Foo: 2 def __init__(self,name,salary): 3 self.name=name 4 self.salary=salary 5 def give_money(self,obj,money): 6 self.salary-=money 7 obj.salary+=money 8 9 f1=Foo('lit1',4000) 10 f2=Foo('lit2',1000) 11 12 f1.give_money(f2,100) 13 14 print(f1.salary) 15 print(f2.salary)
f1可以给f2money,也可以定义两个不同的类进行,不在举例。
类的继承和派生
继承指的是类与类之间的关系,功能之一就是用来解决代码重用问题(比如上一篇文章选课系统中的类,方法基本都是重复的)
继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
class ParentClass1: #定义父类 pass class ParentClass2: #定义父类 pass class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass pass class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类 pass
查看继承的方法,可以根据这个看到父类的查找顺序:
print(SubClass2.__bases__)
结果是:
(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)
以后如果子类调用父类函数,会按照上面的顺序去父类中进行查找。
属性查找
class Foo: def f1(self): print('Foo.f1') def f2(self): print('Foo.f2') self.f1() class Bar(Foo): def f1(self): print('Bar.f1') b=Bar() b.f2()
结果是:
Foo.f2 Bar.f1 |
会按照类的查找顺序进行查找,别自己想当然,呵呵哒!
派生
子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Foo: def f1( self ): print ( 'Foo.f1' ) def f2( self ): print ( 'Foo.f2' ) self .f1() class Bar(Foo): def f1( self ): Foo.f1(<strong> self < / strong>) print ( 'Bar.f1' ) b = Bar() b.f2() |
结果是:
1 2 3 | Foo.f2 Foo.f1 Bar.f1 |
在子类中,新建的重名的函数属性,在编辑函数内功能的时候,有可能需要重用父类中重名的那个函数功能,应该是用调用普通函数的方式,即:类名.func(),此时就与调用普通函数无异了,因此即便是self参数也要为其传值
记住,self也要传值。
组合
软件重用的重要方式除了继承之外还有另外一种方式,即:组合
组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合
class Foo: def f1( self ): print ( 'Foo.f1' ) def f2( self ): print ( 'Foo.f2' ) self .f1() class Goo: def __init__( self ): self .f = Foo() def f1( self ): print ( 'from Goo f1' ) g = Goo() g.f.f1() |
结果是:
Foo.f1 |
f相当于实例化了一个Foo类的对象,作为Goo的一个变量,也可以调用对应的Foo的函数。
子类调用父类的方法
方法一:指名道姓,即父类名.父类方法()
#_*_coding:utf-8_*_ __author__ = 'Linhaifeng' class Vehicle: #定义交通工具类 Country = 'China' def __init__( self ,name,speed,load,power): self .name = name self .speed = speed self .load = load self .power = power def run( self ): print ( '开动啦...' ) class Subway(Vehicle): #地铁 def __init__( self ,name,speed,load,power,line): Vehicle.__init__( self ,name,speed,load,power) self .line = line def run( self ): print ( '地铁%s号线欢迎您' % self .line) Vehicle.run( self ) line13 = Subway( '中国地铁' , '180m/s' , '1000人/箱' , '电' , 13 ) line13.run() |
super()
class Vehicle: #定义交通工具类 Country='China' def __init__(self,name,speed,load,power): self.name=name self.speed=speed self.load=load self.power=power def run(self): print('开动啦...') class Subway(Vehicle): #地铁 def __init__(self,name,speed,load,power,line): #super(Subway,self) 就相当于实例本身 在python3中super()等同于super(Subway,self) super().__init__(name,speed,load,power) self.line=line def run(self): print('地铁%s号线欢迎您' %self.line) super(Subway,self).run() class Mobike(Vehicle):#摩拜单车 pass line13=Subway('中国地铁','180m/s','1000人/箱','电',13) line13.run()
即使没有直接继承关系,super仍然会按照mro继续往后查找,感觉这样会出问题。。。。
1 2 3 4 5 6 7 8 9 10 11 12 | class A: def test( self ): super ().test() class B: def test( self ): print ( 'from B' ) class C(A,B): pass c = C() c.test() #打印结果:from B print (C.mro()) |
结果:
1 2 | from B [< class '__main__.C' >, < class '__main__.A' >, < class '__main__.B' >, < class 'object' >] |
他们的区别
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 | #指名道姓 class A: def __init__( self ): print ( 'A的构造方法' ) class B(A): def __init__( self ): print ( 'B的构造方法' ) A.__init__( self ) class C(A): def __init__( self ): print ( 'C的构造方法' ) A.__init__( self ) class D(B,C): def __init__( self ): print ( 'D的构造方法' ) B.__init__( self ) C.__init__( self ) pass f1 = D() #A.__init__被重复调用 ''' D的构造方法 B的构造方法 A的构造方法 C的构造方法 A的构造方法 ''' #使用super() class A: def __init__( self ): print ( 'A的构造方法' ) class B(A): def __init__( self ): print ( 'B的构造方法' ) super (B, self ).__init__() class C(A): def __init__( self ): print ( 'C的构造方法' ) super (C, self ).__init__() class D(B,C): def __init__( self ): print ( 'D的构造方法' ) super (D, self ).__init__() f1 = D() #super()会基于mro列表,往后找 ''' D的构造方法 B的构造方法 C的构造方法 A的构造方法 ''' |
当你使用super()函数时,Python会在MRO列表上继续搜索下一个类。只要每个重定义的方法统一使用super()并只调用它一次,那么控制流最终会遍历完整个MRO列表,每个方法也只会被调用一次(注意注意注意:使用super调用的所有属性,都是从MRO列表当前的位置往后找,千万不要通过看代码去找继承关系,一定要看MRO列表)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!