美文网首页
类和对象

类和对象

作者: w_wm_m | 来源:发表于2018-12-01 14:28 被阅读0次

    基础

    class Person:                       #类名     
    
        country = 'China'               #创造了只要是这个类就一定有的属性类
                                        #类属性 静态属性
    
        def __init__(self,name,age,sex):    #对象属性
            self.name = name
            self.age = age
            self.sex = sex
    
        def walk(self,n):          
            print("%s is a %s,%s years old,walk %s steps"%(self.name,self.sex,self.age,n))
    
    
    if __name__ == '__main__':
        tom = Person(name='Tom',age=10,sex='boy')    #实例化
        tom.walk(300)
        print("%s is in %s"%(tom.name,Person.country))
    
    object and class.png

         一个对象的诞生:调用类创建一个名为self的对象,(也可以为其他名字,不过习惯上命名为self),调用__init__()方法初始化,并将self返回。

    class Person:
        country = 'China'
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
            print((id(self)))
    
        def walk(self,n):
            print("%s is a %s,%s years old,walk %s steps"%(self.name,self.sex,self.age,n))
    
    
    if __name__ == '__main__':
        tom = Person(name='Tom',age=10,sex='boy')
        print((id(tom)))
    
    id.png
    由此可以看出self和tom是同一个对象。

    Tips:

    • 对方法的调用,Person.walk(tom)等价于tom.walk()。
    • 对象属性和类属性(静态属性)。从调用方式来说,对象属性只可以通过对象来调用,类属性既可以通过对象调用,也可以通过类调用。从内存方面来说,类属性也就是静态属性(static修饰符)在类加载的时候就已经被分配了内存(存在于静态区)只有一份。而对象属性是非static修饰符,是属于单个实例化的类。每new一个实例就会在内存堆中创建一份,就等于多个拷贝,占内存多,但比较灵活,自己修改自己的属性值,互不影响。
    class Person:                       #类名
    
        country = 'China'               #创造了只要是这个类就一定有的属性类
                                        #类属性 静态属性
    
        def __init__(self,name,age,sex):    #对象属性
            self.name = name
            self.age = age
            self.sex = sex
    
        def walk(self,n):
            print("%s is a %s,%s years old,walk %s steps"%(self.name,self.sex,self.age,n))
    
    
    if __name__ == '__main__':
        tom = Person(name='Tom',age=10,sex='boy')    #实例化
        tom.walk(300)
        tom.country = 'Japan'
        print("%s is in %s"%(tom.name,tom.country))
        print("Person.country = %s"%Person.country)
    
    update_result.png
    • 对于不可变数据类型来说,使用对象.静态属性这种方式想去修改静态属性是不行的,本质上它其实是给tom这个对象添加了一个country的属性,并绑定值为“Japan”。如果想要修改静态属性绑定的值就必须要使用类去调用。Person.country=“Japan”这样去修改。
    class Person:                       #类名
    
        country = ['China']               #创造了只要是这个类就一定有的属性类
                                        #类属性 静态属性
    
        def __init__(self,name,age,sex):    #对象属性
            self.name = name
            self.age = age
            self.sex = sex
    
        def walk(self,n):
            print("%s is a %s,%s years old,walk %s steps"%(self.name,self.sex,self.age,n))
    
    
    if __name__ == '__main__':
        tom = Person(name='Tom',age=10,sex='boy')    #实例化
        tom.walk(300)
        tom.country[0] = 'Japan'
        print("%s is in %s"%(tom.name,tom.country))
        print("Person.country = %s"%Person.country)
    
    result.png
    • 对于可变的数据类型来说,可以通过以上方式去修改静态属性。

    类命名空间和对象命名空间

    • 在类加载时会创建一个类的命名空间,用来存储类中定义的所有名字。静态属性就直接定义到类的命名空间里,而对象属性则绑定到所有的对象。
      命名空间.png
    • 在obj.name会先从obj自己的命名空间里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常。

    组合

    class Person:                       #类名
    
        country = 'China'               #创造了只要是这个类就一定有的属性类
                                        #类属性 静态属性
    
        def __init__(self,name,age,sex,fruit):    #对象属性
            self.name = name
            self.age = age
            self.sex = sex
            self.fruit = fruit
    
        def walk(self,n):
            print("%s is a %s,%s years old,walk %s steps"%(self.name,self.sex,self.age,n))
    
        def eat(self):
            print("%s eat a %s %s %s"%(self.name,self.fruit.shape,self.fruit.color,self.fruit.name))
    
    
    class Fruit:
    
        def __init__(self,name,color,shape):
            self.name = name
            self.color = color
            self.shape = shape
    
        def description(self):
            print("A %s %s %s"%(self.shape,self.color,self.name))
    
    result.png
    • 组合是指在一个类中以另外一个类的对象作为数据属性。

    继承

    class Animals:
        def __init__(self,name,sex):
            self.name = name
            self.sex = sex
    
        def eat(self):
            print("Animals eat")
    
    
    class Dog(Animals):
        def __init__(self,name,sex,owner):
            super().__init__(name,sex)
            self.owner = owner
    
        def eat(self):
            print("Dog eat")
    
        def eat_test(self):
            return super().eat()
    
        def bark(self):
            print("Dog bark")
    
    
    if __name__ == '__main__':
        jim = Dog(name='Jim',sex='boy',owner='Mary')
        jim.eat_test()
    
    super.png

    单继承中几个Tips:

    • 子类如果自己有,一定先使用自己的方法和属性,如果子类没有,可以使用父类的方法和属性。
    • 使用super()函数可以直接调用父类的方法或属性。

    在Python中支持多继承

    class A:
        def test(self):
            print("A")
    
    class B(A):
        def test(self):
            print("B")
    
    class C(A):
        def test(self):
            print("C")
    
    class D(B,C):
        def test(self):
            print("D")
    
    if __name__ == '__main__':
        d = D()
        print(d.test())
    

         多继承中继承顺序问题,以上是典型的钻石继承

    钻石继承.png
         在经典类和新式类中继承顺序有所不同。在经典类中使用深度优先,在新式类中使用广度优先。对于Python3.x来说所有的类都是新式类。就钻石继承而言,新式类继承顺序为B->C->A,经典类的继承顺序为B->A->C。

         多继承中的几个Tips:

    • 新式类中可以使用mro()方法,查看广度优先的继承顺序。(类名.mro())
    • Python3.x中,super()方法是根据广度优先的继承顺序查找上一个类父类。
    • 继承中的两个相关函数
    接口类和抽象类
    from abc import ABCMeta,abstractmethod
    
    class Payment(metaclass=ABCMeta):
        @abstractmethod
        def pay(self,money):
            pass
    
    
    class Wechatpay(Payment):
        def pay(self,money):
            print('微信支付了%s元'%money)
    
    p = Wechatpay() #不调就报错了
    

         Tips:

    • Python中没有接口类,有抽象类,abc模块中的metaclass = ABCMeta,@abstractmethod。
    • 本质是在做代码规范,希望在子类中实现和父类方法名字完全一样的方法。
    • 在Java的角度上看是有区别的:
           Java本来就支持单继承,所以就有了抽象类
           Java没有多继承,所以为了借口隔离原则,设计了接口这个概念,支持多继承。
    • Python既支持单继承也支持多继承,所以对于接口类和抽象类的区别不那么明显,甚至在Python中就没有内置接口类

    多态

    • Python天生支持多态。
    • 鸭子类型:不依赖父类的情况下实现两个相似的类中的同名方法。

    封装

    • 在Python中只要将名字前面加上双下划线,就把这个名字私有化了。
    • 私有化之后,就不能从类的外部直接调用了。
    • 静态属性,静态方法,对象属性都可以私有化。
    • 这种私有化只是从代码级别做了变形,并没有真正的约束。
    • 变形机制__类名__名字,在类外用这个调用,在类内部直接__名字调用。
    三个装饰器函数

    property

    @property装饰器的作用:负责把一个方法变成属性调用的

    class Person:
        country = 'China'
    
        def __init__(self,name,age,sex):
            self.name = name
            self.__age = age
            self.__sex = sex
    
        @property
        def age(self):
            return self.__age
    
        @age.setter
        def age(self,new_age):
            self.__age = new_age
    
        @age.deleter
        def age(self):
            del self.__age
    
    
    if __name__ == '__main__':
        tom = Person('Tom',18,'boy')
        print(tom.age)
        tom.age = 20
        print(tom.age)
        del tom.age
        print(tom.age)
    

    classmethod

    当方法操作只涉及静态属性的时候使用

    class Person:
        country = 'China'
    
        def __init__(self,name,age,sex):
            self.name = name
            self.__age = age
            self.__sex = sex
    
        @classmethod
        def change_country(cls,new_country):
            cls.country = new_country
    
    
    if __name__ == '__main__':
        tom = Person('Tom',18,'boy')
        print(tom.country)
        Person.change_country('Jan')
        print(tom.country)
    

    staticmethod

    面向对象规范如果一个方法既和对象没有关系,也和类没有关系,那么就使用@staticmethod将其变成一个静态方法。

    class Person:
        country = 'China'
    
        def __init__(self,name,age,sex):
            self.name = name
            self.__age = age
            self.__sex = sex
    
        @staticmethod
        def get_info():
            name = input("name:")
            age = input("age:")
            sex = input("sex:")
    
    if __name__ == '__main__':
        Person.get_info()
    

    相关文章

      网友评论

          本文标题:类和对象

          本文链接:https://www.haomeiwen.com/subject/xsxffqtx.html