• 面向对象进阶


    isinstance和issubclass

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

    class Foo(object):
         pass
      
    obj = Foo()
      
    isinstance(obj, Foo)

    issubclass(sub, super)检查sub类是否是 super 类的派生类 

    class Foo(object):
        pass
     
    class Bar(Foo):
        pass
     
    issubclass(Bar, Foo)

    反射

    反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

    python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

    class A:
        def func(self):
            print('in func')
    
    a = A()
    a.name = 'alex'
    a.age = 63
    ret = getattr(a,'name') #通过变量名的字符串形式取到的值
    
    sss = input('>>>')
    print(getattr(a,sss))
    class A:
        def func(self):
            print('in func')
    
    a = A()
    a.name = 'alex'
    a.age = 63
    #反射对象的方法
    ret = getattr(a,'func')
    ret()
    class Foo:
        f = '类的静态变量'
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
        def say_hi(self):
            print('hi,%s'%self.name)
    
    obj=Foo('egon',73)
    
    #检测是否含有某属性
    print(hasattr(obj,'name'))
    print(hasattr(obj,'say_hi'))
    
    #获取属性
    n=getattr(obj,'name')
    print(n)
    func=getattr(obj,'say_hi')
    func()
    
    print(getattr(obj,'aaaaaaaa','不存在啊')) #报错
    
    #设置属性
    setattr(obj,'sb',True)
    setattr(obj,'show_name',lambda self:self.name+'sb')
    print(obj.__dict__)
    print(obj.show_name(obj))
    
    #删除属性
    delattr(obj,'age')
    delattr(obj,'show_name')
    delattr(obj,'show_name111')#不存在,则报错
    
    print(obj.__dict__)
    #导入当前模块
    import sys
    
    
    def s1():
        print 's1'
    
    
    def s2():
        print 's2'
    
    
    this_module = sys.modules[__name__]
    
    hasattr(this_module, 's1')
    getattr(this_module, 's2')
    
    #导入模块也可以反射
    def test():
        print('from the test')
    """
    程序目录:
        module_test.py
        index.py
     
    当前文件:
        index.py
    """
    
    import module_test as obj
    
    #obj.test()
    
    print(hasattr(obj,'test'))
    
    getattr(obj,'test')()

    __str__和__repr__

    内置的类方法和内置的函数之间有千丝万缕的联系

    改变对象的字符串显示__str__,__repr__

    自定制格式化字符串__format__

    class A:
        def __str__(self):
            return "A's object"
    a = A()
    
    print(a)  #a.__str__ #打印一个对象的时候,就是调用a.__str__
    '''
    object里有一个__str__,一旦被调用,就返回调用这个方法的对象地址
    %s str() 直接打印 实际上都是走的__str__
    %r repr() 实际上都是走的__repr__
    repr 是str的备胎,但str不能做repr的备胎
    srt(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法
    有,那么他返回的必定是一个str类型,如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__
    repr(),只会找__repr__,如果没有找父类的
    '''
    class B:
    
         def __str__(self):
             return 'str : class B'
    
         def __repr__(self):
             return 'repr : class B'
    
    
    b=B()
    print('%s'%b)
    print('%r'%b)
    '''
    str函数或者print函数--->obj.__str__()
    repr或者交互式解释器--->obj.__repr__()
    如果__str__没有被定义,那么就会使用__repr__来代替输出
    注意:这俩方法的返回值必须是字符串,否则抛出异常
    '''

    __del__

    class Foo:
    
        def __del__(self):
            print('执行我啦') 
    
    f1=Foo()
    del f1
    print('------->')

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

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

    __len__

    内置的方法有很多
    不一定全都在object中
    class A:
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __len__(self):
            return len(self.__dict__)
    a = A()
    print(len(a))
    
    class B:
        def __len__(self):
            return 10
    b= B()
    print(len(b))

    __call__

    class Foo:
    
        def __init__(self):
            pass
        
        def __call__(self, *args, **kwargs):
    
            print('__call__')
    
    
    obj = Foo() # 执行 __init__
    obj()       # 执行 __call__

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

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

    item系列

    class Foo:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
            
        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]
        
    f = Foo('zack',38,'')
    print(f['name'])
    f['hobby'] = ''
    print(f.hobby,f['hobby'])
    del f.hobby  #object 原生支持 __delattr__
    del f['hobby']  #通过自己实现的 
    print(f.__dict__)

    __new__

    #init是初始化方法,__new__是构造方法:创建一个对象
    class A:
        def __init__(self):
            self.x = 1
            print('in init function')
        def __new__(cls,*args,**kwargs):
            print('in new function')
            return object.__new__(A,*args,**kwargs)
    a = A()
    print(a,x)
    '''
    设计模式
    单例模式:一个类始终只有一个实例
    当你第一次实例化这个类的时候 就创建一个实例化的对象
    当你之后再来实例化的时候 就用之前的创建的对象
    '''
    class A:
        __instance = False
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def __new__(cls,*args,**kwargs)
            if cls.__instance:
                return cls.__instance
            cls.__instance = object.__new__(A)
            return cls.__instance
    
    e = A('egg',38)
    z = A('zack',25)
    print(egg)
    print(zack)

    __eq__

    class A:
        def __init__(self,name):
            self.name = name
        def __eq__(self,other):
            if self.__dict__ == other.__dict__:
                return True
            else:
                return False
                
    obj1 = A('egg')
    obj2 = A('egg')
    print(obj1 == obj2)

    __hash__

    class A:
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __hash__(self):
            return hash(str(self.a)+str(self.b))
    a = A()
    print(hash(a))
    class FranchDeck:
        ranks = [str(n) for n in range(2,11)] + list('JQKA')
        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
    
    deck = FranchDeck()
    print(deck[0])
    from random import choice
    print(choice(deck))
    print(choice(deck))
    
    from random import shuffle
    shuffle(deck)
    print(deck[:5])
    纸牌游戏
    '''
    有一个类的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 Person:
        def __init__(self,name,age,sex,weight):
            self.name = name
            self.sex = sex
            self.age = age
            self.weight = weight
        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)
    
    person = Person('sole',20,'',80)
    person1 = Person('sole',21,'',80)
    print(set((person,person1)))    
    去重
  • 相关阅读:
    查找算法
    顺序表和链表
    队列
    Redis系列教材 (二)- 运行
    Redis系列教材 (一)- windows教程
    Maven系列教材 (十三)- Eclipse 中创建父子-聚合项目
    Maven系列教材 (十一)- 使用Eclipse导入一个Maven风格的SSM项目
    Maven系列教材 (十)- 使用Eclipse创建一个Maven风格的SSM项目
    Maven系列教材 (九)- 在Eclipse中创建maven风格的java web项目
    Maven系列教材 (八)- 用命令行创建Maven风格的java web项目
  • 原文地址:https://www.cnblogs.com/soleZ/p/8329293.html
Copyright © 2020-2023  润新知