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。

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

会按照类的查找顺序进行查找,别自己想当然,呵呵哒!

派生

子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。

class Foo:
    def f1(self):
        print('Foo.f1')

    def f2(self):
        print('Foo.f2')
        self.f1()

class Bar(Foo):
    def f1(self):
        Foo.f1(self)
        print('Bar.f1')


b=Bar()
b.f2()

结果是: 

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继续往后查找,感觉这样会出问题。。。。

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())

结果:

from B
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]

他们的区别

#指名道姓
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列表

  

 

原文地址:https://www.cnblogs.com/litzhiai/p/7978310.html