python面向对象

python面向对象笔记

课程链接:点击打开

15-python-面向对象-类属性-上

  1. 类也是对象

  2. 给类增加一个属性(在类的外面通过赋值的方法):

    class Money:
    	pass
    one=Money()
    Money.count=1 #给类增加一个属性
    print(Money.count)
    print(Money.__dict__)
    

16-python-面向对象-类属性-下

  1. 类增加属性的方式二(在类的内部通过赋值的方法):

    class Money:
    	age=28
        count=1
        num=666
        
    one=Money()
    print(Money.count)
    print(Money.age)
    print(Money.__dict__)
    

17-python-面向对象-类属性-查询属性

  1. 通过对像访问类属性:优先从对像自身上查找属性,找到则结束,如果没有找到,根据class找到对象对应的类,到这个类里面查找。

    print(one.age)
    print(one.aount)
    
  2. 更改对象的类:

    class text:
        pass
    one.__class__ = text#更改对象的类
    print(one.age)#不能访问
    

18-python-面向对象-类属性-修改属性

  1. 通过类名修改

    class Money:
    	age=28
        count=1
        num=666
        
    Money.age=22
    print(Money.age)
    
  2. 不能通过对象修改类属性

19-python-面向对象-类属性-删除属性

  1. del 类名 类属性

    del  Money.age
    
  2. 不能通过对象删除,del语句只能删除直系属性

  3. 类的属性的增、删、改只能通过类来访问,查询的时候可以通过对象和类来访问!

20-python-面向对象-类属性的内存存储

  1. 类属性的内存存储问题:一般情况下,属性存储在__dict__字典当中,有些内置对象没有这个属性,一般对象可以直接修改__dict__属性,类对象的__dict__为只读,默认无法修改。

    class Money:
    	age=28
        count=1
        num=666
            
    one=Money()
    one.__dict__['age'] = 999#对象的__dict__可以被修改
    print(one.age)
    

21-python-面向对象-类属性被各个对象所共享

  1. class Money:
    	age=28
        count=1
        num=666
            
    one=Money()
    two=Money()
    print(one.age)
    print(two.age)
    
  2. 查看一个类的所有属性通过类名.__dict__来查看

22-python-面向对象-类属性对象属性总结对比

23-python-面向对象-限制对象属性的添加__slots__

  1. class Person:
        __slots__=['age']  #只有slots所限定的属性
        pass
    p1 = Person()
    p1.age = 18
    p1.name = '小狗' #将报错
    

方法相关

24-python-面向对象-方法的讲解说明

25-python-面向对象-方法的概念和作用

  1. 描述一个目标的行为动作

  2. 和函数非常类似,都封装了一系列动作,都可以被调用之后执行一系列行为动作,最主要的时调用方式

    class Persondef eat2(self):
            print(1)
            print(2)
            print(3)
    p = Person()
    p.eat2()
    

26-python-面向对象-类、对象、类对象、实例对象、实例的叫法规范

27-python-面向对象-方法的划分依据

  1. 实例方法:默认第一个参数需要接收到一个实例

  2. 类方法:默认第一个参数需要接收到一个类

  3. 静态方法:一个默认参数也不接受

  4. 注意:1.划分依据是:方法第一个参数必须要接受的的数据类型。2.不管是哪一种给类型方法,都储存在类当中,没有在示例当中的。3.不同类型方法调用方式不同。

    class Person:
    	def eat2(self):
            print('这是一个实例方法',self)
        @classmethod
        def leifangfa(cls):
            print('这是一个类方法',cls)
        @staticmethod
        def jiangtaifanfa():
            print('这是一个静态方法')
    

28-python-面向对象-方法的储存问题

  1. 函数也是对象
  2. 方法也保存在类的__dict__中,没有在实例当中的

29-python-面向对象-小节掌握说明

30-python-面向对象-实例方法

  1. 标准的调用方法:使用实例调用实例方法,不用手动调,解释器会把调用对象(实例)本身传递过去。如果实例方法没有接受任何单数则会报错。

    class Person:
        def eat(self,food):#self可以是aa、bb 等,一般是self
            print('在吃饭',food)
    
    p = Person()
    p.eat('土豆')
    #-------------------------------
    class Person:
        def eat(): #报错,因为实例方法必第一个必须接收实例作为第一个参数
            print('在吃饭')
    
    p.eat()
            
    
  2. 其他的的调用方法:使用类调用、间接调用,他们的本质就是直接找到函数本身来调用。

31-python-面向对象-类方法

  1. 类方法可以被实例调用,也可以被类调用。

    class Person:
        @classmethod #装饰器的作用:在保证原函数不变的情况下,直接给这个函数增加一些功能
        def leifangfa(cls,a):
            print("这是一个类方法" , a)
            
    Person.leifangfa(123)
    
    p = person()
    p.leifangfa(666)
    
    func = Person.leifangfa
    func(111)
    

32-python-面向对象-静态方法

  1. 既可以通过类调用,也可以通过示例调用

    class Person:
        @staticmethod #装饰器的作用:在保证原函数不变的情况下,直接给这个函数增加一些功能
        def jingtai(cls):
            print("这是一个类方法")
            
    Person.jingtai()
    
    p = Person()
    p.jingtai()
    
    func = Person.jingtai
    func()
    

33-python-面向对像-不同类型的方法中访问不同类型的属性的权限问题

  1. 访问类属性:通过类和实例

    访问实例属性:只能通过实例

    class Person:
        age = 0
        def shilifangfa(self):
            print(self)
            print(self.age)
            print(self.num)
        @classmethod
        def leifangfa(cls):
            print(cls)
            print(cls.age)
            print(cls.num)   #不能通过类访问实例属性
        @staticmethod
        def jingtaifangfa():
            print(Person.age) #可以通过类访问类属性
    P = person()
    P.num = 10
    

34-python-面向对象-补充-元类

  1. 元组:创建类对象的类

    Screenshot_20200830_101925_tv.danmaku.bili
num = 1
print(num.__class__)  #输出int
%------------------------------------------
s = "abc"
print(s.__class__)   #输出str
%------------------------------------------
class Person:
	pass
p = Person()
print(p.__class__)  #输出Person
%------------------------------------------
print(int.__class__)  #输出type

35-python-面向对象-补充-类对象的创建方式

  1. 调用type函数创建

    def run(self):
        print(self)
    xxx = type("Dog",(),{"count":0,"run":run})
    print(xxx)
    print(xxx.__dict__)
    
    d.xxx()   #不是d.Dog
    print(d)
    d.run()
    
    Screenshot_20200830_104601_tv.danmaku.bili

36-python-面向对象-补充-类对象创建时,元类的查找机制

  1. 类的创建流程:

    1. 检测类对象是否有明确的__mateclass__属性。
    2. 检测父类中是否存在__mateclass__属性。
    3. 检测模块中是否存在__mateclass__属性。
    4. 通过内置的type这个元类来创建这个类对象。
    #1模块的指定
    __metaclass__ = xxx
    #2
    class Animal:
        pass
    #3
    class Dog(Animal):
        pass
    #4
    class Dog:
        __metaclass__ = xxx
        pass
    

37-python-面向对象-补充-类的描述

  1. class Person:
        """
        关于这个类的描述,类的作用,类的构造函数等等;类属性的描述
        Attributes:
        	count: int 代表人的个数
        """
        count = 1
        def run(self, disance, step):
            """
            这个方法的作用效果
            :param distance:blahblah
            :param step:blahblah
            :return:
            """
            print("跑步")
            return  distance,step
    help(Person)  #
    

38-python-面向对象-补充-注释文档的生成(抽取源文件的注释)

  1. 注释文档不包括源码,只包括函数名和它的描述

    方式1.使用内置的模块:pydoc。具体步骤:

    1. 查看文档描述:python3 -m pydoc 模块名称
    2. 启动本地服务,浏览文档 :python3- m pydoc-p 666
    3. 生成指定模块html文件:python3 -m pydoc -w 模块名称

    命令行命令:

    cd <代码路径>
    python --help
    python -m pydoc <文件名>      #
    python -m pydoc -k <关键字>   #列出文件名中包含关键字的文件
    python -m pydoc -p <端口号>   #指定一个未用的端口号
    python -m pydoc -b           #自动指定端口号
    python -m pydoc -w <文件名>   #在当前目录生成一个html文件
    
  2. 还有其他方法,只是要安装第三方模块。

私有属性

39-python-面向对象-补充-私有化属性的概念和意义

  1. 概念:限定属性的访问的方法。

40-python-面向对象-补充-访问权限测试区域划分

  1. 注意:python并没有真正的私有化支持,但是,可以使用下划线完成伪私有的效果。如_y__z

41-python-面向对象-私有化属性-共有属性

  1. 共有属性可以通过

    1. 类的内部访问,也就是类的实例方法中
    2. 子类(延伸类)内部访问
    3. 模块其他位置访问
      1. 类访问(父类,派生类)
      2. 实例访问(父类实例,派生类实例)
    4. 跨模块访问
      1. import形式导入
      2. from 模块 import * 导入
    class Animal:
        x = 10
        def test(self):
            print(Animal.x)
            print(self.x)
            pass
    %----------------------
    class Dog(Animal):
        def test2(self):
            print(Dog.x)
            print(self.x)
            pass
    
    a = Animal()
    a.test()		#类的内部访问,通过类内部定义的函数访问
    
    d = Dog()
    d.test2()		#延伸类的访问(通过延伸类内部定义的函数访问)
    
    print(Animal.x)		#模块的其他部分
    print(Dog.x)
    print(a.x)
    print(b.x)
    
    import xxx              #模块的其他部分访问
    print(xxx.a)
    from xxx import *
    print(a)
    
    

42-python-面向对象-补充-私有化属性-受保护的属性

  1. class Animal:
        _x = 10
        def test(self):
            print(Animal._x)
            print(self._x)
         pass
    #--------------------
    class Dog(Animal):
        def test2(self):
            print(Dog._x)
            print(self._x)
         pass
    
    a = Animal()
    a.test()		#类的内部访问
    
    d = Dog()
    d.test2()		#延伸类的访问
    
    print(Animal._x)		#模块的其他部分,可以强行访问,有警告
    print(Dog._x)
    print(a._x)
    print(b._x)
    
    import xxx              #模块的其他部分访问,不可访问
    print(xxx.a)
    from xxx import *
    print(a)
    

43-python-面向对象-私有化属性-私有属性

  1. class Animal:
        __x = 10
        def test(self):         #定义一个实例方法
            print(Animal.__x)
            print(self.__x)
         pass
    
    #--------------------
    
    class Dog(Animal):
        def test2(self):
            print(Dog.__x)
            print(self.__x)
         pass
    
    a = Animal()
    a.test()		#类的内部访问,可以访问
    
    d = Dog()
    d.test2()		#延伸类的访问,不可以访问
    
    print(Animal.__x)		# 模块的其他部分,不可访问
    print(Dog.__x)
    print(a.__x)
    print(d.__x)
    
    a = 1
    import xxx              #模块的其他部分访问,不可访问
    print(xxx.a)
    from xxx import *
    print(a)
    

44-python-面向对象-补充-私有化属性-私有属性-名字重整机制

  1. 名字重整:改_x为另外一个名称,如:_类名_x

  2. 目的:

    1. 防止外界直接访问
    2. 防止被子类同名称属性覆盖
  3. 可以用重整后的名字访问

    class Animal:
        __x = 10
        def test(self):
            print(Animal.__x)
            print(self.__x)
            pass
    
    print(Animal.__dict__)
    ptint(Animal,_Animal__x)
    

45-python-面向对象-补充-私有属性的应用场景

  1. 数据保护 2.数据过滤

    class Person:
        #作用:当我们创建好一个实例对对象之后,会自动调用这个方法,来初始化这对象
        #init是单词初始化initialization的省略形式
        def __init__(self)
        	self.__age = 18
        def setAge(self,value):
            if isinstance(value,int) and 0<value<200:
            	self.__age = value
            else:
                print("您输入的数据有误,请重新输入")
        def getAge(self):
            return self.__age
        
            
    p1 = Person()
    p1.setAge(20)
    p2 = Person()
    print(p1.getAge())   #访问age
    
    print(p1.__age)      #报错,只能在类内部访问
    print(p2.__age)
    

46-python-面向对象-补充-变量添加下划线的规范

  1. xx_:避免与系统关键字冲突
  2. __xx__:系统内置

只读属性

47-python-面向对象-补充-只读属性的概念和意义

  1. 只读属性的概念:一个属性只能读取,不能写入

48-python-面向对象-补充-只读属性-方案一

  1. 全部隐藏,通过私有化,即不能读取,也不能写入; 部分公开,通过方法实现(有弊端)

class Person:
def init(self): #初始化方法,通过方法设置属性
self.__age = 18
def getAge(self): #部分公开,通过方法实现
return self.__age
p1 = person()
print(p1.getAge())


## 49-python-面向对象-只读属性-方案一的优化

1. ```python
class Person(object):
    def __init__(self):
        self.__age = 18
     # 主要作用:可以以使用属性的方法来使用这个方法
    @property
    def age(self):   #部分公开,通过方法实现
        return self.__age
p1 = person()
print(p1.age())

50-python-面向对象-property的作用

  1. property的作用:将“一些属性的操作方法”关联到另一个属性,间接地管理私有属性

    class C(object):
        def getx(self): return self._x
        def setx(self,value): self._x = value
        def delx(self): del self._x
        x = property(getx, setx, delx)
    

51-python-面向对象-补充-经典类和新式类

  1. 经典类:没有继承object

  2. 新式类:继承object

    class Person:
        pass
    
    print(Person.__bases__)  #查看父类(基类)k
    
  3. 在python2中,定义一个类,没有显式的继承自object,那么这个类就是一个继承类,显式的继承自object,他才是一个新式类。

    在python3中,定义一个类,会隐式的继承object,所以默认情况下,就已经是一个新式类。

    建议,无论在python2和3,都显式的继承object。

52-python-面向对象-补充-property在新式类中的使用

  1. property函数方法

    class Person(object):
        def __init__(self):
            self.__age = 18
        def get_age(self):
            ruturn self.__age
        def set_age(self, value):
            self.__age = value
        age = property(get_age, set_age)
        
    p = Person()
    print(p.age)
    
    p.age = 30
    print(p.age)
    print(p.__dict__) #输出只有_person__age: 
    
    

    2.装饰器的方式

     class Person(object):
        def __init__(self):
            self.__age = 18
               @property
               def age(self):
                   return self.__age
               @age.setter
               def age(self, value):
                   delf.__age = value
    
        p = Person()
        p.age = 20    #既可以读取也可以设置
    

53-python-面向对象-补充-property在经典类中的使用(切换版版本为python2)

  1. 在经典类中,property只会关联读取方法,不会关联设置和删除方法。

    class Person(object):
        def __init__(self):
            self.__age = 18
        def get_age(self):
            ruturn self.__age
        def set_age(self, value):
            self.__age = value
        age = property(get_age, set_age)
        
    p = Person()
    print(p.age)   #可以读取,不会报错
    
    p.age = 30     #不会设置属性,而是增加了一个age属性
    print(p.age)
    print(p.__dict__) #输出_person__age和age
    
    #--------------------------
    
    #         装饰器方法
    
    #--------------------------
    class Person(object):
           def __init__(self):
               self.__age = 18
           @property
           def age(self):
               return self.__age
           @age.setter
           def age(self, value):
               delf.__age = value
              
       p = Person()
       print(p.age)   #可以读取,不会报错
    
       p.age = 30     #不会设置属性,而是增加了一个age属性
       print(p.age)
    
       print(p.__dict__) #输出_person__age和age
    

54-python-面向对象-只读属性-方案二

  1. 虽然是私有属性,任然可以通过两种方法设置__age属性:

    p._Person__age=xxx

    p.__dict__['_Person__age']=xxx

  2. 做只读属性的方式二:

     class Person:
        #当我们通过实例.属性 = 值,给一个实力增加一个属性,或者修改属性的时候,就会自动调用这个方法,
        #在这个方法内部才会正真地把这个属性,以及对应的数据存储到__dict__字典里面
        def __settter__(self, key, value):
            print(key, value)
            #1.判定,key,是否是我们要设置的只读属性
            if key = "age" and key in self.__dict__.keys():#只能新增属性,不能修改属性
               print("这个属性是只读属性,不能设置数据")
            #2.如果不是只读属性,就给他添加到实例里面去
            else:
               #self.key = value  #这样会陷入死循环
               self.__dict__[key] = value
    

常用的内置属性

55-python-面向对象-常用内置属性

  1. 类属性:

    1. __dict__:类属性
    2. __bases__:类的所有父类构成元组
    3. __doc__类的文档字符
    4. __name__类名
    5. __module__类定义所在模块
  2. 实例属性:

    1. __dict__:类的实例
    2. __class__:实例对应的类

56-python-面向对象-补充-私有方法

  1. 方法:在函数名前加两个下划线,与属性私有化相同,名字重整机制是相同的。

    class Person:
        def __run(self):
            print("run")
    p = Person()
    print(Person.__dict__)
    

内置方法

57-python-面向对象-补充-内置特殊方法-使用意义

  1. 内置方法的作用;完成一些特定的功能

58-python-面向对象-内置特殊方法-__str__

  1. 给初始化方法__init__里边传递参数,即可创建不同的对象

    class Person:
        def __init__(self,n,a):
            self.name = n
            self.age = a
    p1 = Person("zpc", 18) #可创建不同的对象
    
  2. 通过定义__str__,就可以通过print(<对象>)来查看指定的返回值

    class Person:
        def __init__(self,n,a):
            self.name = n
            self.age = a
        def __str__(self):
            return "这个人的姓名是%s,这个人的年龄是%s"%(self.name, self.age)
    p1 = Person("zpc",18) #可创建不同的对象
    
    s=str(p1)
    print(s)
    

59-python-面向对象-内置的特殊方法-__repr__

  1. __repr__面向的对象是开发人员(解释器);__str__面向的对象是用户。

    def Person:
        def __init__(self):
            return"repr"
    
  2. 如果没有定义__str__,那么str也返回的是__repr__的内容

  3. 触发__str__的方法:

    1. 直接打印:print(p1)
    2. str方法:s=str(p1) print(s)
  4. 触发__repr__的方法:

    1. s=repr(p1) print(s)
    2. 在交互模式里面将对象名称写出,敲回车

60-python-面向对象-内置特殊方法-__call__-概念和作用

  1. __call__的作用:使得对象具有当作函数来调用的能力(将对象变为可调用对象)

    class Person:
        def __call__(self):
            print("xxx")
        pass
    p = Person()
    p()            #调用__call__函数
    

61-python-面向对象-__call__应用场景的简单案例

  1. 首先创建一个类,类的属性只有一个(p_type),然后创建一个__call__方法(只接收一个参数p_color),这样就可以通过<实例>(p_color)

    class PenFactory:
        def __init__(self, p_type):
            self.p_type = p_type       #这个类只有一个属性
        def __call__(self, p_color):
            print("创建了一个%s类型的画笔,他是%s颜色的"%(self.p_type, p_color))
    gangbiF = penFactory("钢笔")       #创建一个对象
    gangbiF('红色')
    

一些操作

62-python-面向对象-索引操作(使对象具有像字典一样的索引操作)

  1. 以索引的方式操作python序列:

    1. 增、改:p[1] = 666p['name'] = sz
    2. 查:p[name]p[1]
    3. 删除:del p[name]del p[1]
  2. 需要一个字典属性,才可以对对象进行索引操作。

    class Person:
        def __init__(self):
            self.cache = {}              #定义cache属性,为一个字典
        def __setitem__(self, key, value):
            self.cache[key] = value
        def __getitem__(self, key):
            return self.cache[key]
        def __delitem__(self, key):
            del self.cache[key]
    p = Person()
    p['name'] = 'sz'  #执行这行代码的时候,会调用第一个方法
    print(p['name'])  #调用第二个方法
    

63-python-面向对象-切片操作

  1. 索引是对一个进行增、删、改、查;切片是对多个进行增、删、改、查。
  2. python3中,‘切片操作’统一由‘索引操作’进行管理!
    1. def __setitem__(self, key, value):
    2. def __getitem__(self, item):
    3. def __delitem__(self, key):
class Person:
    def __init__(self):
        self.items = [1, 2, 3, 4, 5, 6, 7, 8]  #定义了一个items属性
        
    def __setitem__(self, key, value):
        if isinstance(key,silce):
        self.items[key] = value           #注意切片操作只能修改,不能新增
        #self.items.[key.start: key.stop: key.step] = value  #这样赋值也可以
    def __getitem__(self, key):
        return(key.items[key])            #这里可能有错
    def __delitem__(self, key):
        del self[key]
p = Person()
p[0: 4: 2] = ["a","b"]
print(p.items[0: 4: 2])

64-python-面向对象-比较操作-映射的内置方法、65-python-面向对象-比较操作-映射的内置方法

  1. 为对象定义比较操作,调用此方法,就可以使对象可以向数一样比较大小!

    class Person:
        def __init__(self, age, height):
            self.age = age
            self.height = height
        def __eq__(self, other):
            return self.age == other.age   #指定相等的比较通过哪个属性比较,
        def __ne__(self, other):
            return self.age != other.age   #指定相等的比较通过哪个属性比较,
    p1 = Person(18, 180)
    p2 = Person(19, 183)
    print(p1 == p2)
    #类似的还有:
    #gt >
    #ge >=
    #lt <
    #le <=  
    #可以通过调换参数的方式定义比较方法,进而简化代码
    

66-面向对象-比较操作-方案2(通过装饰器自动补全)

  1. import functools
    
    @functools.total_ordering      #此装饰器会自动补全所需要的方法
    class Person 
        def __lt__(self, other):
            pass
        def __eq__(self, other):
            pass
    

67-python-面向对象-比较操作-上下文布尔值

  1. 非空即为True

  2. 此方法使对象可以被作为一个布尔值使用。

    class Person():
        def __bool__(self):    #通过bool值判定实例是True或False
            return False       #这里也可以是一个返回布尔值的语句
        pass
    
    p = Person()
    if p:
        print("xx")
        
    

68-python-面向对象-遍历操作-__getitem__

  1. 遍历操作:

    1. 让我们创建的对象可以使用for循环进行遍历
      1. 实现__getitem__方法
      2. 实现__iter__方法
    2. 让我们创建的对象可以使用next函数进行访问(迭代器)
    class Person:
        def __init__(self):
            self.result = 1
        def __getitem__(self, item):
            self.result += 1
            if self.result >=6:   #不满足时,跳出循环
                raise StopIteration("停止遍历")
                
            return relf.result
        pass
    p = person()
    
    for i in p:    #当执行for循环时,自动进入__getitem__方法,使用这个方法的返回值作为数据
        print(i)
    

69-python-面向对象-遍历操作-__iter__

  1. __iter__的优先级高于__getitem__

    class Person:
        def __init__(self):
            self.result = 1
        def __getitem__(self, item):
            self.result += 1
            if self.result >=6:   #不满足时,跳出循环
                raise StopIteration("停止遍历")
                
            return relf.result
        def __iter__(self):
            print("hfkjasdf")
    p = person()
    
    for i in p:    #当执行for循环时,自动进入__geritem__方法,使用这个方法的返回值作为数据
        print(i)
    
  2. 可迭代对象包含迭代器。

  3. 如果一个对象拥有__iter__方法,其是可迭代对象;如果一个对象拥有__next__方法,其是迭代器。

  4. 定义可迭代对象,必须实现__iter__方法;定义迭代器,必须实现__iter____next__方法。

你也许会问,结论c与结论b是不是有一点矛盾?既然一个对象拥有了__next__方法就是迭代器,那为什么迭代器必须同时实现两方法呢?

因为结论a,迭代器也是可迭代对象,因此迭代器必须也实现__iter__方法。

  1. 可迭代对象与迭代器
  2. 首先调用__iter__,返回一个迭代器,然后调用__next__方法;

    class Person:
        def __init__(self):
            self.result = 1
        def __getitem__(self, item):
            self.result += 1
            if self.result >=6:   #不满足时,跳出循环
                raise StopIteration("停止遍历")
            #return iter([1,2,3,4])    如果返回是迭代器,则自动进入迭代器的__next__方法   
            return relf.result
        def __iter__(self):
            return self
        def __next__(self):
            self.result += 1
            if self.result >=6:   #不满足时,跳出循环
                raise StopIteration("停止遍历")    
            return relf.result
    p = person()
    
    for i in p:    
        print(i)
    

70-python-面向对象-遍历操作-__next__

  1. 通过next函数访问迭代器:

    class Person:
        def __init__(self):
            self.result = 1
        def __getitem__(self, item):
            self.result += 1
            if self.result >=6:   #不满足时,跳出循环
                raise StopIteration("停止遍历")
            #return iter([1,2,3,4])    如果返回是迭代器,则自动进入迭代器的__next__方法   
            return relf.result
        
        def __next__(self):
            self.result += 1
            if self.result >=6:   #不满足时,跳出循环
                raise StopIteration("停止遍历")    
            return relf.result
    p = person()
    
    print(next(p))   #直接进入__next__方法
    print(next(p))
    print(next(p))
    print(next(p))
    print(next(p))   #抛出异常,停止遍历
    

71-python-面向对像-遍历操作-迭代器的复用

  1. class Person:
        def __init__(self):
            self.age = 1
            
        def __iter__(self):
            self.age = 1   # 如果没有这行命令,那么迭代器只能使用一次
            return self
        
        def __next__(self):
            self.age += 1
            if self.age >=6:   #不满足时,跳出循环
                raise StopIteration("停止遍历")    
            return relf.age
        
    p = person()
    for i in p:
        print(i)
    import collection
    print(isinstance(p, collection.Iterator))  
    #返回值为True,表明确实是一个迭代器,需要同时有两个方法__iter__、__next__
    next(p)  #只要有一个方法__next__就可以访问
    

72-python-面向对象-遍历操作-迭代器-可迭代的判定依据

  1. import collection
    print(isinstance(p, collection.Iterable))#判定是否为可迭代对象,只要一个方法__iter__就可以 
    
  2. 一个可迭代对象一定可以通过for in访问,可以通过for in访问的不一定是可迭代对象

73-python-面向对象-遍历操作-iter的使用(没听懂)

  1. 通过next()函数访问对象,要想让iter()对创建的对象起作用,需要在类里边定义方法:__getitem__或者:__iter____next__(这两个方法必须同时都需要)。
  2. iter(<要转换的对象>,<停止数值>)

74-面向对象-描述器-概念和作用

  1. 概念和作用:描述器是一个对象,可以描述一个属性的操作;其作用是对属性的操作做验证和过滤,如对一个人的年龄赋值时,不能赋值为负数,这是需要验证和过滤,但由于属性数量多,不能在赋值前进行验证,所以用到描述器,每次验证时就会进入描述器中进行相关操作

75-python-面向对象-描述器-定义方式1-property

class Person:
    def __init__(self):
        self.__age = 10
        
    @property
    def age(self):
        return self.__age
    
    @age.setter
    def age(self, value):
        if value < 0:
            value = 0
        self.__age = value
        
    @age.deleter
    def age(self):
        del self.__age
        
        
p = Person()
p.age             #注意:这里的age是方法里面的age,不是属性的age
del p.age

76-python-面向对象-描述器-定义方式2

  1. 对方式一进行优化,即多个属性时,由于操作内容不同,在主类中代码会过于繁琐,为简化代码,将属性的操作方法封装到类中,在主类中对方法类的实例对象进行操作即可

    class Age:        #描述器类
        def __get__(self, instance, owner):
            print("get")
        def __set__(self, instance, value):
            print("set")
        def __delete__(self, instance):
            print("delete")
            
    class Person:     #主类
        age = Age()   
        
    p = Person()
    p.age = 10
    
    # 创建一个描述器的类,它的实例就是一个描述器
    # 这个类要有__get__  __set__ 这样的方法
    # 这种类是当做工具使用的,不单独使用
    class M:
        def __init__(self, x=1):
            self.x = x
            
        def __get__(self, instance, owner):
            return self.x
        
        def __set__(self, instance, value):
            self.x = value
            
    # 调用描述器的类
    class AA:
        m = M() # m就是一个描述器
        
    aa = AA()
    aa.m # 1
    aa.m = 2
    aa.m # 2
    
    
  2. 注意:不能通过Person类调用age属性,只能通过Person类定义的对象来调用age属性。

  3. Person、Age必须全是经典类。

  4. 被操作属性值的存储问题:描述器定义方式二中有描述器类和主类两个类,当操作由主类产生的两个实例对象的同一个属性时,这个属性要被赋予不同的值,即两个实例赋值互不影响,这就要研究属性值的存储问题。由于操作的时同一个属性,所以进入的是同一个描述器类,如果将值存储在描述器类产生的实例上,由于存储地址相同,后面的赋值会覆盖前面的赋值;而主类产生的两个实例对象不同,分配了不同内存,因此,应将属性值存储在主类的实例中

77

78

79-

80

81-python-面向对象-数据储存问题

82

83-python-面向对象-生命周期

  1. 生命周期:指的是一个对象从诞生到消亡的过程,当一个对象被创建时,会在内存中分配相应的空间进行储存,当这个对象不再使用,为了节约内存,就会把这个对象释放。
  2. 涉及的问题1.如何监听一个对象的生命。2.python是如何掌握一个对象的生命。
  3. 监听对象的生命周期
    1. __new__方法
    2. __init__方法
    3. __del__方法
  4. 内存管理机制

84-

85-

86、87-python-面向对象-内存管理机制-引用计数器

  1. python内部使用引用计数,来保持追踪内存中的对象。记录Python内部记录了对象有多少个引用,即引用计数,当对象被创建时就创建了一个引用计数,当对象不再需要时,这个对象的引用计数为0时,它被当作垃圾回收。系统会去检查那些引用计数为0的对象,然后清除其在内存的空间。当内存中有不再使用的部分时,垃圾收集器就会把他们清理掉。

  2. 总结一下对象会在一下情况下引用计数加1:

    1. 对象被创建:x=4
    2. 另外的别人被创建:y=x
    3. 被作为参数传递给函数:foo(x)
    4. 4作为容器对象的一个元素:a=[1,x,‘33’]
  3. 引用计数减少情况

    1. 一个本地引用离开了它的作用域。比如上面的foo(x)函数结束时,x指向的对象引用减1。
    2. 对象的别名被显式的销毁:del x ;或者del y
    3. 对象的一个别名被赋值给其他对象:x=789
    4. 对象从一个窗口对象中移除:myList.remove(x)
    5. 窗口对象本身被销毁:del myList,或者窗口对象本身离开了作用域。
    class Person:
        pass
    p1 = Person()  #计数器+1
    print(sys.getrefcount(p1))  #这里输出的是2
    p2 = p1     #计数器+1 这个过程将p2指向Person()的内存
    
    del p2      #计数器-1
    del p1      #计数器-1
    
  4. 查看引用计数,需要包import syssys.getrefcount(对象),注意:这里也引用了对象,所以计数器会增加1。

88-python-面向对象-内存管理机制-引用计数器-循环引用

  1. 内存管理机制:当一个对象被引用,则+1;当一个对象被删除,则-1;为0时,被释放。

  2. 循环引用:

    循环引用
    import objgraph
    #objgraph.count()收入类名,查看垃圾回收器,跟踪对象个数
    class Person:
        pass
    class Dog:
        pass
    
    p = Person()
    d = Dog()
    
    print(objgraph.count("Person"))#1
    print(objgraph.count("Dog"))#1
    
    p.pet = d
    d.master = p
    
    del p
    del d
    
    print(objgraph.count("Person"))#1
    print(objgraph.count("Dog"))#1
    
    

89-面向对象-内存管理机制-垃圾回收机制-垃圾检测流程

  1. 垃圾回收机制的作用:从经历过“引用技术机制”任然未被释放的对象中找到“循环引用”,干掉相关对象。

  2. 怎样找到“循环引用”

    1. 收集所有的“容器对象”,通过一个链表进行引用(容器对象:可引用其他对象的对象)
    2. 针对每一个容器对象,通过一个变量gc_refs来记录当前对应的引用计数
    3. 对于每个容器对象,找到他引用的其他的容器对象,为这个其他的容器对象-1
    4. 经过3后,如果一个容器对象的引用数为0,则可以回收
    垃圾回收机制-垃圾检测流程

89-python-面向对象-内存管理机制-垃圾回收机制-分代回收

96、97、98、99、100、101-python-面向对象-小节案例-1

  1. 做一个计算器,实现一些加减乘除的基本操作,然后打印操作的结果

    面向过程的方法:这样的方法调用很麻烦,不断地保存变量,不断地传递变量。

    def jia(n1, n2):
        return n1 + n2
    def jian(n1, n2):
        return n1 - n2
    def cheng(n1, n2):
        return n1 * n2
    #计算(2 + 6 - 4) + 5
    r1 = jia(2, 6)
    r2 = jian(r1, 4)
    r3 = jia(r2, 5)
    print(r3)
    

    如 果不要不断地保存变量、不断地传递变量,就这样稿!

    result = 0
    def first_value(v):
        global result
        result = v
    def jia(n):
        global result
        return += n
    def jian(n):
        global result
        return -= n
    def cheng(n1, n2):
        global result
        return *= n
    #计算(2 + 6 - 4) + 5
    first_value(2)
    jia(5)
    jian(4)
    cheng(5)
    print(result)
    

    上面的代码任然不完美,下面通过类方法定义计数器!

    class Calculator:
        __result = 0
        
        @classmethod
        def first_value(cls, v):
            cls.__result = v
            
        @classmethod
        def jia(cls, n):
            cls.__result += n
            
        @classmethod
        def jian(cls, n):
            cls.__result -= n
            
        @classmethod
        def cheng(cls, n):
            cls.__result *= n
        
        @classmethod  
        def show(self):
            print("计算结果为:%d" %self.__result)
            
    Calculator.first_value(2)
    Calculator.jia(6)
    Calculator.jian(4)
    Calculator.cheng(5)
    Calculator.show()
    

    这样不能同时使用这个计数器同时进行多个运算,要想解决以上问题,这样做(通过实例方法):

    class Calculator:
        def __init__(self, num):
            self.__result = num
            
        def jia(self, n):
            self.__result += n
        
        def jian(self, n):
            self.__result -= n
            
        def cheng(self, n):
            self.__result *= n
            
        def show(self):
            print("计算结果为: %d"%self.__result)
    
    c1 = Calculator(2)
    c1.jia(6)
    c1.jian(4)
    c1.cheng(5)
    c1.show()
    

    在上面的代码上增加一些容错处理:

    class Calculator:
        def __init__(self, num):
            if not isinstance(num, int)
            	raise TypeError("当前这个数据的类型有问题,应该是一个整形数据")
            self.__result = num
            
        def jia(self, n):
             if not isinstance(num, int)
            	raise TypeError("当前这个数据的类型有问题,应该是一个整形数据")
            self.__result += n
        
        def jian(self, n):
             if not isinstance(num, int)
            	raise TypeError("当前这个数据的类型有问题,应该是一个整形数据")
            self.__result -= n
            
        def cheng(self, n):
             if not isinstance(num, int)
            	raise TypeError("当前这个数据的类型有问题,应该是一个整形数据")
            self.__result *= n
            
        def show(self):
            print("计算结果为: %d"%self.__result)
    
    c1 = Calculator(2)
    c1.jia(6)
    c1.jian(4)
    c1.cheng(5)
    c1.show()
    #-------------------上面代码冗余度很高!可以这样改(定义一个检查函数)-----------------------
    class Calculator:
        def check_num(self, num):
            if not isinstance(num, int):
                raise TypeError("当前这个数据类型有问题,应该是一个整型数据")
        def __init__(self, num):
            self.check_num(num)
            self.__result = num
            
        def jia(self, n):
             self.check_num(n)
            self.__result += n
        
        def jian(self, n):
              self.check_num(n)
            self.__result -= n
            
        def cheng(self, n):
              self.check_num(n)
            self.__result *= n
            
        def show(self):
            print("计算结果为: %d"%self.__result)
    
    c1 = Calculator(2)
    c1.jia(6)
    c1.jian(4)
    c1.cheng(5)
    c1.show()
    

    101、不想破坏代码的完整性?通过装饰器来给函数增加功能

    class Calculator:
        def check_num_zsq(func):
            def inner(self, n):     #这个函数的返回值要跟被修饰函数的返回值相同
                if not isinstance(n, int):
                    raise TypeError("当前这个数据的类型有问题,应该是一个整形数据")
                return func(self, n) #因为这个func有返回值,所以是return(func(self, n))
       @check_num_zsq 
       def __init__(self, num):
            self.__result = num
            
       @check_num_zsq
       def jia(self, n):
            self.__result += n
            
       @check_num_zsq
       def jian(self, n):
            self.__result -= n
            
       @check_num_zsq
       def cheng(self, n):
            self.__result *= n
            
       def show(self):
        	print("计算机的结果是:%d" % self.__result)
            
            
    c1 = Caculator(2)
    c1.jia(6)
    c1.jian("a")
    c1.cheng(5)
    c1.show()
    

102-python-面向对象-小节案例-7

为了不让外界当作函数调用所定义的装饰器,就把装饰器弄成私有方法:

class Calculator:
    
    def __check_num_zsq(func):
        def inner(self, n):     #这个函数的返回值要跟被修饰函数的返回值相同
            if not isinstance(n, int):
                raise TypeError("当前这个数据的类型有问题,应该是一个整形数据")
            return func(self, n) #因为这个func有返回值,所以是return(func)
        
   @__check_num_zsq 
   def __init__(self, num):
        self.__result = num
        
   @__check_num_zsq
   def jia(self, n):
        self.__result += n
        
   @__check_num_zsq
   def jian(self, n):
        self.__result -= n
        
   @__check_num_zsq
   def cheng(self, n):
        self.__result *= n
        
   def show(self):
    	print("计算机的结果是:%d" % self.__result)
        
        
c1 = Caculator(2)
c1.jia(6)
c1.jian("a")
c1.cheng(5)
c1.show()

103、104-python-面向对象-小节案例-8

现在要求播报用户的每一个操作!开启声音的计算器!实现这种功能有好几种方案,调用Windows操作系统下面的一个接口就可以!

import win32com.client
#1.创建一个播报对象
speaker = win32com.client.Dispatch("SAPI.SpVoice")
#2.通过这个播报对象,直接播放相应的语音字符串就可以
speaker.speak("我的名字是zpc")
#-----------------------------------------#
          #通过函数实现
#-----------------------------------------#
class Calculator:
    def __say(self, word):   #这里必须是一个实例方法
    	#1.创建一个播报对象
		speaker = win32com.client.Dispatch("SAPI.SpVoice")
		#2.通过这个播报对象,直接播放相应的语音字符串就可以
		speaker.speak(word)

    def __check_num_zsq(func):
        def inner(self, n):     #这个函数的返回值要跟被修饰函数的返回值相同
            if not isinstance(n, int):
                raise TypeError("当前这个数据的类型有问题,应该是一个整形数据")
            return func(self, n) #因为这个func有返回值,所以是return(func(self, n))
   @__check_num_zsq 
   def __init__(self, num):
        self.__say(num)
        self.__result = num
        
   @__check_num_zsq
   def jia(self, n):
        self.__say(n)
        self.__result += n
        
   @__check_num_zsq
   def jian(self, n):
        self.__say(n)
        self.__result -= n
        
   @__check_num_zsq
   def cheng(self, n):
        self.__say(n)
        self.__result *= n
        
   def show(self):
        self.__say("计算机的结果是:%d" % self.__result)
    	print("计算机的结果是:%d" % self.__result)
        
        
c1 = Caculator(2)
c1.jia(6)
c1.jian("a")
c1.cheng(5)
c1.show()

105-python-面向对象-小节案例

不想破坏代码的结构吗?那使用装饰器好喽!

#-----------------------------------------#
          #通过装饰器实现
#-----------------------------------------#
class Calculator:
    def __say__zsq(func):
        def inner(self, n):
        #1.创建一个播报对象
		speaker = win32com.client.Dispatch("SAPI.SpVoice")
		#2.通过这个播报对象,直接播放相应的语音字符串就可以
		speaker.speak(word)
       	return func(self, n)
    return inner

    def __check_num_zsq(func):
        def inner(self, n):     #这个函数的返回值要跟被修饰函数的返回值相同
            if not isinstance(n, int):
                raise TypeError("当前这个数据的类型有问题,应该是一个整形数据")
            return func(self, n) #因为这个func有返回值,所以是return(func(self, n))
 
   @__check_num_zsq #先验证再播放
   @__say_zsq
   def __init__(self, num):
        self.__say(num)
        self.__result = num
        
   @__check_num_zsq
   @__say_zsq
   def jia(self, n):
        self.__say(n)
        self.__result += n
        
   @__check_num_zsq
   @__say_zsq
   def jian(self, n):
        self.__say(n)
        self.__result -= n
        
   @__check_num_zsq
   @__say_zsq
   def cheng(self, n):
        self.__say(n)
        self.__result *= n
        
   def show(self):
        self.__say("计算机的结果是:%d" % self.__result)
    	print("计算机的结果是:%d" % self.__result)
        
        
c1 = Caculator(2)
c1.jia(6)
c1.jian(4)
c1.cheng(5)
c1.show()

装饰器的嵌套:

106-python-面向对象-小节案例-11

带参数的装饰器怎么定义呢?

def creat_say_zsq(word=""):
    def __say_zsq(func):
        def inner(self, n):
            #1.创建了一个播报对象
            speaker = win32com.client.client.Dispatch("SAPI.SpVoice")
            #2.通过这个播报对象直接播报相应的语音字符串就可
            speaker.Speak(word + str(n))
            return func(self, n)
        
       return inner

	return __say_zsq
#下面分析一下这个函数,最外层creat_say_zsq是一个函数,他创建了一个装饰器,传入参数,并将装饰器返回!

    def __check_num_zsq(func):
        def inner(self, n):     #这个函数的返回值要跟被修饰函数的返回值相同
            if not isinstance(n, int):
                raise TypeError("当前这个数据的类型有问题,应该是一个整形数据")
            return func(self, n) #因为这个func有返回值,所以是return(func(self, n))
 
   @__check_num_zsq #先验证再播放
   @creat__say_zsq
   def __init__(self, num):
        self.__say(num)
        self.__result = num
        
   @__check_num_zsq
   @creak__say_zsq("加")
   def jia(self, n):
        self.__say(n)
        self.__result += n
        
   @__check_num_zsq
   @@creak__say_zsq("减去")
   def jian(self, n):
        self.__say(n)
        self.__result -= n
        
   @__check_num_zsq
   @creak__say_zsq("乘以")
   def cheng(self, n):
        self.__say(n)
        self.__result *= n
        
   def show(self):
        self.__say("计算机的结果是:%d" % self.__result)
    	print("计算机的结果是:%d" % self.__result)
        
        
c1 = Caculator(2)
c1.jia(6)
c1.jian(4)
c1.cheng(5)
c1.show()

107-python-面向对象-小节案例-12

注意:show函数不能通过上面的装饰器进心装饰,因为show只接收一个参数,而其他的函数都接收两个参数!

要让计算器播报结果怎么办呢?

可以这样:

  def show(self):
        self.__say("计算机的结果是:%d" % self.__result)
            #1.创建了一个播报对象
            speaker = win32com.client.client.Dispatch("SAPI.SpVoice")
            #2.通过这个播报对象直接播报相应的语音字符串就可
            speaker.Speak("计算机的结果是:%d" % self.__result)
            print("计算机的结果是:%d" % self.__result)

进一步的,如果在其他系统运行代码,就要改两处,这是麻烦的,现在进一步,可以这样操作(定义了一个播报器函数,以后调用这个函数即可,要改的话,只改这一个函数就可以了):

import win32com.client

class Caculator:
    def __say(self, word):
         #1.创建了一个播报对象
         speaker = win32com.client.client.Dispatch("SAPI.SpVoice")
         #2.通过这个播报对象直接播报相应的语音字符串就可
          speaker.Speak(word 
    
	def __creat_say_zsq(word=""):
		def __say_zsq(func):
       		 def inner(self, n):
                self.__say(word  + str(n))
         	   return func(self, n)
        
        return inner

	return __say_zsq
#下面分析一下这个函数,最外层creat_say_zsq是一个函数,他创建了一个装饰器,传入参数,并将装饰器返回!

    def __check_num_zsq(func):
        def inner(self, n):     #这个函数的返回值要跟被修饰函数的返回值相同
            if not isinstance(n, int):
                raise TypeError("当前这个数据的类型有问题,应该是一个整形数据")
            return func(self, n) #因为这个func有返回值,所以是return(func(self, n))
 
   @__check_num_zsq #先验证再播放
   @__creat__say_zsq
   def __init__(self, num):
        self.__say(num)
        self.__result = num
        
   @__check_num_zsq
   @__creak__say_zsq("加")
   def jia(self, n):
        self.__say(n)
        self.__result += n
        
   @__check_num_zsq
   @__creak__say_zsq("减去")
   def jian(self, n):
        self.__say(n)
        self.__result -= n
        
   @__check_num_zsq
   @__creak__say_zsq("乘以")
   def cheng(self, n):
        self.__say(n)
        self.__result *= n
        
   def show(self):
        self.__say("计算机的结果是:%d" % self.__result)
    	print("计算机的结果是:%d" % self.__result)
        
        
c1 = Caculator(2)
c1.jia(6)
c1.jian(4)
c1.cheng(5)
c1.show()

我们再加一个功能,使上面定义的类可以返回__result,用什么方法呢?当然是描述器喽!

class Caculator:
    #省略了一堆代码!
    @property
    def result(self):
        return self.__result
c1 = Caculator(10)
c1.jia(6)
c1.jian(4)
c1.cheng(5)
c1.show

print(c1.result)

109-python-面向对象-小节案例-14

每次做运算都要写一个c1.,这太麻烦了!有什么办法可以不写呢?

在定义的每个运算里面加一个return(self)就可以了呀!这样的编程思路为:链式编程。

  @__check_num_zsq #先验证再播放
   @__creat__say_zsq
   def __init__(self, num):
        self.__say(num)
        self.__result = num
        return self
        
   @__check_num_zsq
   @__creak__say_zsq("加")
   def jia(self, n):
        self.__say(n)
        self.__result += n
        return self
        
   @__check_num_zsq
   @__creak__say_zsq("减去")
   def jian(self, n):
        self.__say(n)
        self.__result -= n
        return self
        
   @__check_num_zsq
   @__creak__say_zsq("乘以")
   def cheng(self, n):
        self.__say(n)
        self.__result *= n
        return self
    
    def show(self):
        self.__say("计算机的结果是:%d" % self.__result)
    	print("计算机的结果是:%d" % self.__result)
        return self
#这样就可以这样运算了:
c1.Caculator(10)
c1.jia(6).jian(4).cheng(5).show()
print(c1.result)

在加一个清零的操作:

def clear(self):
    self.__result = 0
    result self

python三大特性

110-python-面向对象-三大特性-封装

111-python-面向对象-三大特性-继承-概念

继承时,子类有父类的一些属性的使用权

父类也叫做:超类、基类

子类也叫做:派生类

112-python-面向对象-三大特性-继承-语法格式

继承的分类:单继承、多继承。

单继承:只继承了一个父类。

多继承:继承了多个父类。继承了多个类的话,就有很多父类的属性

class Animal:
    pass
class xxx:
    pass

class Dog(Animal, xxx):#多继承
    pass

class Dog(Animal):#单继承
    pass

113-python-面向对象-三大属性-type和object

怎么看一个类的父类:__bases__

怎么看一个实例的类:__class__type()函数

在Python的世界中

  1. object是父子关系的顶端,所有的数据类型的父类都是它;

  2. type是类型实例关系的顶端,所有对象都是它的实例的。

  3. 先来看看type和object:

    它们都是type的一个实例,表示它们都是类型对象。

    typeobject都属于type objects。type objects翻译过来就是类型对象了。类型对象的特征:

    1. 它们用于表示程序中的抽象数据类型。例如,我们定义的一个类User会代表系统中所有的用户。int会代表系统中所有整形数字。
    2. 它们能被继承。这意味着你可以利用存在的类型对象创造出新的类型对象。已经存在的类型对象是新的类型对象的超类。
    3. 它们能被实例化。这意味着你可以利用已经存在的类型对象创造出新的实例对象。前者是后者的type
    4. 类型对象的类型是type
    5. 它们有时会被成为类型有时会被称为
  4. Object是type的一个实例

    >>> object.class
    <type 'type'>
    >>> object.bases  # object 无父类,因为它是链条顶端。
    ()
    

#Type是object的子类

type.bases
(<type 'object'>,)
type.class  # type的类型是自己
<type 'type'>



​```python
>>> object

>>> type

#查看Dog的父类
print(Dog.__bases__)
print(Animal.__bases__)  #输出object
#object也是一个类

114-python-面向对象-三大特性-继承-对资源的影响

  1. 资源的继承
  2. 资源的使用
  3. 资源的覆盖
  4. 资源的累加

115-python-面向对象-三大特性-继承-资源的继承

设置不同权限属性的类型和方法,在继承当中进行测试,看在子类中能不能访问到这些资源。

class Animal:
    a = 1
    _b = 2 #受保护的属性
    __c = 3 #私有属性
    
    def t1(self):
        print("t1")
        
    def _t2(self):
        print("t2")
        
    def __t3(self):
        print("t3")
        
    def __init__(self):
        print("init Animal")
        
class Person(Animal):
    def test(self):
        print(self.a)
        print(self._b)
        print(self.__c)#私有属性不可访问
        
        self.t1()
        self._t2()
        self.__t3()#私有方法无法继承
        self.__init__()
        
p = Person()
p.test()
#注意:这里的属性a是继承了父类的使用权,而不是又复制了一个a

116-python-面向对象-三大特性-继承-资源继承的重申

class B:
    age = 10
    
class A(B):
    pass

print(A.age) #打印10
A.age = 9 #这时并没有改变B类中的age属性,而是在A中又创建了一个age属性,并赋值9

ses__`

怎么看一个实例的类:__class__type()函数

在Python的世界中

  1. object是父子关系的顶端,所有的数据类型的父类都是它;

  2. type是类型实例关系的顶端,所有对象都是它的实例的。

  3. 先来看看type和object:

    它们都是type的一个实例,表示它们都是类型对象。

    typeobject都属于type objects。type objects翻译过来就是类型对象了。类型对象的特征:

    1. 它们用于表示程序中的抽象数据类型。例如,我们定义的一个类User会代表系统中所有的用户。int会代表系统中所有整形数字。
    2. 它们能被继承。这意味着你可以利用存在的类型对象创造出新的类型对象。已经存在的类型对象是新的类型对象的超类。
    3. 它们能被实例化。这意味着你可以利用已经存在的类型对象创造出新的实例对象。前者是后者的type
    4. 类型对象的类型是type
    5. 它们有时会被成为类型有时会被称为
  4. Object是type的一个实例

    >>> object.class
    <type 'type'>
    >>> object.bases  # object 无父类,因为它是链条顶端。
    ()
    

#Type是object的子类

type.bases
(<type 'object'>,)
type.class  # type的类型是自己
<type 'type'>



​```python
>>> object

>>> type

#查看Dog的父类
print(Dog.__bases__)
print(Animal.__bases__)  #输出object
#object也是一个类

114-python-面向对象-三大特性-继承-对资源的影响

  1. 资源的继承
  2. 资源的使用
  3. 资源的覆盖
  4. 资源的累加

115-python-面向对象-三大特性-继承-资源的继承

设置不同权限属性的类型和方法,在继承当中进行测试,看在子类中能不能访问到这些资源。

class Animal:
    a = 1
    _b = 2 #受保护的属性
    __c = 3 #私有属性
    
    def t1(self):
        print("t1")
        
    def _t2(self):
        print("t2")
        
    def __t3(self):
        print("t3")
        
    def __init__(self):
        print("init Animal")
        
class Person(Animal):
    def test(self):
        print(self.a)
        print(self._b)
        print(self.__c)#私有属性不可访问
        
        self.t1()
        self._t2()
        self.__t3()#私有方法无法继承
        self.__init__()
        
p = Person()
p.test()
#注意:这里的属性a是继承了父类的使用权,而不是又复制了一个a

116-python-面向对象-三大特性-继承-资源继承的重申

class B:
    age = 10
    
class A(B):
    pass

print(A.age) #打印10
A.age = 9 #这时并没有改变B类中的age属性,而是在A中又创建了一个age属性,并赋值9

你可能感兴趣的:(面向对象,python,python,面向对象编程)