类和对象

基础

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)
类和对象_第1张图片
result.png
  • 对于可变的数据类型来说,可以通过以上方式去修改静态属性。

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

  • 在类加载时会创建一个类的命名空间,用来存储类中定义的所有名字。静态属性就直接定义到类的命名空间里,而对象属性则绑定到所有的对象。
    类和对象_第2张图片
    命名空间.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))
类和对象_第3张图片
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())

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

类和对象_第4张图片
钻石继承.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()

你可能感兴趣的:(类和对象)