zoukankan      html  css  js  c++  java
  • python 面向对象的进阶

    isinstance和issubclass

    isinstance(obj,cls)检查是否obj是否是类 cls 的对象

    isinstance(obj,cls)检查是否obj是否是类 cls 的对象

    class A:pass
    class B(A):pass
    a = A()
    print(isinstance(a,A))   #t
    print(issubclass(B,A)) #t
    print(issubclass(A,B)) #f

    反射

    反射:是用 字符串类型的名字 去操作 变量。有 hasattr、getattr、 setattr、 delattr 四个相关函数。
    与eval相似,但eval主要用来网络传输,操作文件或别人的代码,存在安全隐患。反射值操作写在内存中的名字,没有安全隐患。
    反射对象中的属性和方法(getattr)
    class A:
        def func(self):
            print('in func')
    
    a = A()
    a.name = 'alex'
    a.age = 63
    # 反射对象的属性
    ret = getattr(a,'name')  # 通过变量名的字符串形式取到的值
    print(ret)
    print(a.__dict__)
    变量名 = input('>>>')   # func
    print(getattr(a,变量名))
    print(a.__dict__[变量名])  # 不能用于方法
    
    # 反射对象的方法
    a.func()
    ret = getattr(a,'func')
    ret()
    反射类中的属性和方法(getattr/hasattr)
    class A:
        price = 20
        @classmethod
        def func(cls):
            print('in func')
    # 反射类的属性
    # A.price
    print(getattr(A,'price'))
    
    # 反射类的方法 :classmethod staticmethod
    # A.func()
    if hasattr(A,'func'):
        getattr(A,'func')()
    反射模块的属性和方法
    import my
    反射模块的属性
    print(my.day)
    print(getattr(my,'day'))
    
    反射模块的方法
    getattr(my,'wahaha')()

    # 内置模块也能用
    #time
    asctime
    import time
    print(getattr(time,'time')())
    print(getattr(time,'asctime')())
    反射自己模块的属性和方法
    def qqxing():
        print('qqxing')
    year = 2018
    import sys
    print(sys.modules['__main__'].year)
    # 反射自己模块中的变量
    # print(getattr(sys.modules['__main__'],'year'))
    
    # 反射自己模块中的函数
    # getattr(sys.modules['__main__'],'qqxing')()
    变量名 = input('>>>')
    print(getattr(sys.modules[__name__],变量名))
    要反射的函数有参数怎么办?当有多个参数不同时,不可使用
    print(time.strftime('%Y-%m-%d %H:%M:S'))
    print(getattr(time,'strftime')('%Y-%m-%d %H:%M:S'))
    一个模块中的类也能反射得到,只要是有 . 的都可以反射。
    import my
    print(getattr(my,'C')()) # <my.C object at 0x0046BB70>
    if hasattr(my,'name'):
        getattr(my,'name')
    setattr 、delattr
    # 重要程度半颗星
    # setattr  设置修改变量
    class A:
        pass
    a = A()
    setattr(a,'name','nezha')
    setattr(A,'name','alex')
    print(A.name)
    print(a.name)
    
    # delattr 删除一个变量
    delattr(a,'name')
    print(a.name)
    delattr(A,'name')
    print(a.name)
    类的内置方法
    内置的类方法 和 内置的函数 之间有着千丝万缕的联系。
    __str__/__repr__
    双下方法
    obj.__str__  str(obj) 
    obj.__repr__ repr(obj)
    class Teacher:
        def __init__(self,name,salary):
            self.name = name
            self.salary = salary
        def __str__(self):
            return "Teacher's object :%s"%self.name
        def __repr__(self):
            return str(self.__dict__)
        def func(self):
            return 'wahaha'
    nezha = Teacher('哪吒',250)
    print(nezha)  # 打印一个对象的时候,就是调用a.__str__
    print(repr(nezha))
    print('>>> %r'%nezha)

    a.__str__ --> object object 里有一个__str__,一旦被调用,就返回调用这个方法的对象的内存地址 l = [1,2,3,4,5] # 实例化 实例化了一个列表类的对象 print(l) 走的是list类里面的__str__ %s str() 直接打印 实际上都是走的__str__ %r repr() 实际上都是走的__repr__ print(obj)/'%s'%obj/str(obj)的时候,(打印一个对象)
    实际上是内部调用了obj.__str__方法,如果str方法有,那么他返回的必定是一个字符串。
    如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__。
    父类是自定义类时,如果没有__str__方法,会先到父类找str,再找自己的repr。再去找objiect类的str,repr
    总之,object在最后。

    repr(),只会找__repr__,如果没有找父类的。
    repr 是str的备胎,但str不能做repr的备胎
    内置的方法有很多
    不一定全都在object中
    class Classes:
        def __init__(self,name):
            self.name = name
            self.student = []
        def __len__(self):
            return len(self.student)
        def __str__(self):
            return 'classes'
    py_s9= Classes('python全栈9期')
    py_s9.student.append('二哥')
    py_s9.student.append('泰哥')
    print(len(py_s9)) #走len
    print(py_s9)#走str
    一个应用的小例子

    __del__

    析构方法,当对象在内存中被释放时,自动触发执行。

    注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

    class A:
        def __del__(self):   # 析构函数: 在删除一个对象之前进行一些收尾工作
            self.f.close()
    a = A()
    a.f = open()   # 打开文件 第一 在操作系统中打开了一个文件 拿到了文件操作符存在了内存中
    del a          # a.f 拿到了文件操作符消失在了内存中
    del a   # del 既执行了这个方法,又删除了变量

    __call__

    对象后面加括号,触发执行。

    注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

    class A:
        def __init__(self,name):
            self.name = name
        def __call__(self):
            '''
            打印这个对象中的所有属性
            '''
            for k in self.__dict__:
                print(k,self.__dict__[k])
    a = A('alex')()

    item系列 __getitem__\__setitem__\__delitem__

    class A:
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def __getitem__(self, item):
            if hasattr(self,item):
                return self.__dict__[item]
        def __setitem__(self, key, value):
            self.__dict__[key] = value
        def __delitem__(self, key):
            del self.__dict__[key]
    a = A('lily',23)
    print(a['name'])
    a['age']=18
    print(a.age)
    print(a['age'])
    del a['age']# 通过自己实现的
    del a.age   # object 原生支持  __delattr__
    print(a.__dict__)
    (因为self的属性和值,通过字典实现,这个方法也可用于列表,用于下标取值)

    __new__

    # __init__ 初始化方法
    # __new__  构造方法 : 创建一个对象
    class A:
        def __init__(self):
            self.x=1
            print('in init')
        def __new__(cls, *args, **kwargs):
            print('in new')
            return object.__new__(A)
    a = A()
    # in new
    # in init
    # 单例模式(一个类始终只有一个对象)
    class A:
        __obj = False
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def __new__(cls, *args, **kwargs):
            if cls.__obj:
                return  cls.__obj
            cls.__obj = object.__new__(A)
            return cls.__obj
    a1 = A('lisa',19)
    print(a1.__dict__)
    a2 = A('JISOO',20)
    a2.cloth = 'red-T'
    print(a2.__dict__)
    print(a1.__dict__) #与a2一样
    单例模式(一个类始终只有一个对象)

    __hash__

    class A:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
        def __hash__(self):
            return hash(self.name+self.sex)
    a = A('lisa',19,'women')
    b = A('jenny',23,'women')
    print(hash(a))
    print(hash(b))

    __eq__

    未定义是比较的是内存地址,可以自定义比较的内容,灵活应用。
    class A:
        def __init__(self,name):
            self.name = name
        def __eq__(self, other):
            if self.__dict__ == other.__dict__:
                return True
            else:
                return False
    a = A('lisa')
    b = A('lisa')
    print(a==b)
        有一个类的init方法如下:
        class Person:
            def __init__(self,name,age,sex,weight):
                self.name = name
                self.sex = sex
                self.age = age
                self.weight = weight
        假设有100个person的对象,
        若两个对象的obj1,obj2的name和sex属性相同
        即obj1.name==obj2.name and obj1.sex==obj2.sex
        我们认为两个对象为同一个对象,已知一个列表中的100个对象,对这100个对象进行去重。
        提示:
            重写Person类重的两个内置方法
    
    class A:
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
    
        def __eq__(self, other):
            if self.name == other.name and self.sex == other.sex:
                return True
            return False
    
        def __hash__(self):
            return hash(self.name + self.sex)
    a = A('egg','',38)
    b = A('egg','',37)
    print(set((a,b)))   # unhashable
    应用(面试题)-- set 依赖对象的 hash eq
    import json
    from collections import namedtuple
    Card = namedtuple('Card',['rank','suit'])   # rank 牌面的大小 suit牌面的花色
    class FranchDeck:
        ranks = [str(n) for n in range(2,11)] + list('JQKA')   # 2-A
        suits = ['红心','方板','梅花','黑桃']
    
        def __init__(self):
            self._cards = [Card(rank,suit) for rank in FranchDeck.ranks
                                            for suit in FranchDeck.suits]
    
        def __len__(self):
            return len(self._cards)
    
        def __getitem__(self, item):
            return self._cards[item]
    
        def __setitem__(self, key, value):
            self._cards[key] = value
    
        def __str__(self):
            return json.dumps(self._cards,ensure_ascii=False)
    
    deck = FranchDeck()
    print(deck)
    from random import choice
    print(choice(deck)) #deck是对象,不是列表也可以吗
    # print(choice(deck))
    # 洗牌
    from random import shuffle
    shuffle(deck)
    # print(deck)      #把列表序列化后输出
    # print(deck[:5]) #依赖于item方法
    应用- 纸牌游戏























  • 相关阅读:
    asp.net发送邮件
    jquery+TreeView 级联 复选框 checkbox 级联
    100层楼,两个会坏的杯子,测从哪层开始坏【算法思想】
    flex中dragdrop不响应的原因
    flex 中urlrequest缓存问题
    程序员技术练级攻略
    consistent hashing
    入门教材
    烙饼啊烙饼{转自ITEO
    杂乱的工作记录
  • 原文地址:https://www.cnblogs.com/olivia2018/p/8330206.html
Copyright © 2011-2022 走看看