zoukankan      html  css  js  c++  java
  • Python基础第十六天:面向对象进阶

    目录

      isinstance 和 issubclass

      反射

        setattr

        delattr

        getattr

        hasattr

      __str__ 和 __repr__

      __del__

      item系类

        __getiem__

        __setitem__

        __delitem__

      __new__

      __call__

      __len__

      __hash__

      __eq__

      isinstance 和 issubclass

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

    class Foo(object):
        pass
    
    obj = Foo()
    
    print(isinstance(obj,Foo)) #True

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

    class Foo(object):
        pass
    
    class Bar(Foo):
        pass
    
    print(issubclass(Bar,Foo)) #True

      反射

      1、什么是反射

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

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

      四个可以实现自省的函数

      下列方法适用于类和对象 (一切皆对象,类本身也是一个对象)

    def hasattr(*args, **kwargs): # real signature unknown
        """
        Return whether the object has an attribute with the given name.
        
        This is done by calling getattr(obj, name) and catching AttributeError.
        """
        pass
    hasattr
    def getattr(object, name, default=None): # known special case of getattr
        """
        getattr(object, name[, default]) -> value
        
        Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
        When a default argument is given, it is returned when the attribute doesn't
        exist; without it, an exception is raised in that case.
        """
        pass
    getattr
    def setattr(x, y, v): # real signature unknown; restored from __doc__
        """
        Sets the named attribute on the given object to the specified value.
        
        setattr(x, 'y', v) is equivalent to ``x.y = v''
        """
        pass
    setattr
    def delattr(x, y): # real signature unknown; restored from __doc__
        """
        Deletes the named attribute from the given object.
        
        delattr(x, 'y') is equivalent to ``del x.y''
        """
        pass
    delattr
    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__)
    4个的应用
    True
    True
    egon
    hi,egon
    不存在啊
    {'name': 'egon', 'age': 73, 'sb': True, 'show_name': <function <lambda> at 0x0000000001D22EA0>}
    egonsb
    AttributeError: show_name111
    {'name': 'egon', 'sb': True}
    执行结果
    class Foo(object):
    
        staticField = 'old boy'
    
        def __init__(self):
            self.name = 'wupeiqi'
    
        def func(self):
            return 'func'
    
        @staticmethod
        def bar():
            return 'bar'
    
    print(getattr(Foo,'staticField'))
    print(getattr(Foo,'func'))
    print(getattr(Foo,'bar'))
    类也是对象
    old boy
    <function Foo.func at 0x0000000001E79A60>
    <function Foo.bar at 0x0000000001E79B70>
    执行结果
    import sys
    
    
    def s1():
        print 's1'
    
    
    def s2():
        print 's2'
    
    
    this_module = sys.modules[__name__]
    
    hasattr(this_module, 's1')
    getattr(this_module, 's2')
    反射当前模块成员
    True
    <function s2 at 0x0000000001E99C80>
    执行结果

      导入其他模块,利用反射查找该模块是否存在某个方法 

    def test():
        print('from the test')
    View Code
    """
    程序目录:
        module_test.py
        index.py
     
    当前文件:
        index.py
    """
    
    import module_test as obj
    
    #obj.test()
    
    print(hasattr(obj,'test'))
    
    getattr(obj,'test')()
    View Code
    True
    from the test
    执行结果

      __str__和__repr__

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

      自定制格式化字符串__format__

    #_*_coding:utf-8_*_
    
    format_dict={
        'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
        'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
        'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
    }
    class School:
        def __init__(self,name,addr,type):
            self.name=name
            self.addr=addr
            self.type=type
    
        def __repr__(self):
            return 'School(%s,%s)' %(self.name,self.addr)
        def __str__(self):
            return '(%s,%s)' %(self.name,self.addr)
    
        def __format__(self, format_spec):
            # if format_spec
            if not format_spec or format_spec not in format_dict:
                format_spec='nat'
            fmt=format_dict[format_spec]
            return fmt.format(obj=self)
    
    s1=School('oldboy1','北京','私立')
    print('from repr: ',repr(s1))
    print('from str: ',str(s1))
    print(s1)
    
    '''
    str函数或者print函数--->obj.__str__()
    repr或者交互式解释器--->obj.__repr__()
    如果__str__没有被定义,那么就会使用__repr__来代替输出
    注意:这俩方法的返回值必须是字符串,否则抛出异常
    '''
    print(format(s1,'nat'))
    print(format(s1,'tna'))
    print(format(s1,'tan'))
    print(format(s1,'asfdasdffd'))
    
    =======执行结果===================
    from repr:  School(oldboy1,北京)
    from str:  (oldboy1,北京)
    (oldboy1,北京)
    
    oldboy1-北京-私立
    私立:oldboy1:北京
    私立/北京/oldboy1
    oldboy1-北京-私立
    View Code
    class B:
    
        def __str__(self):
            return 'str : class B'
    
        def __repr__(self):
            return 'repr : class B'
    
    
    b = B()
    print('%s' % b)
    print('%r' % b)
    View Code
    str : class B
    repr : class B
    执行结果

      __del__

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

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

    class Foo:
    
        def __del__(self):
            print('执行我啦')
    
    f1=Foo()
    del f1
    print('------->')
    
    #输出结果
    执行我啦
    ------->
    View Code

      item系列

      __getitem__\__setitem__\__delitem__

    class Foo:
        def __init__(self,name):
            self.name=name
    
        def __getitem__(self, item):
            print(self.__dict__[item])
    
        def __setitem__(self, key, value):
            self.__dict__[key]=value
        def __delitem__(self, key):
            print('del obj[key]时,我执行')
            self.__dict__.pop(key)
        def __delattr__(self, item):
            print('del obj.key时,我执行')
            self.__dict__.pop(item)
    
    f1=Foo('sb')
    f1['age']=18
    f1['age1']=19
    del f1.age1
    del f1['age']
    f1['name']='alex'
    print(f1.__dict__)
    
    ========执行结果=============
    del obj.key时,我执行
    del obj[key]时,我执行
    {'name': 'alex'}
    View Code

     

      __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)
    ================
    in new function
    in init function
    1
    View Code

     

    class Singleton:
        def __new__(cls, *args, **kw):
            if not hasattr(cls, '_instance'):
                cls._instance = object.__new__(cls, *args, **kw)
            return cls._instance
    
    one = Singleton()
    two = Singleton()
    
    two.a = 3
    print(one.a)
    # 3
    # one和two完全相同,可以用id(), ==, is检测
    print(id(one))
    # 29097904
    print(id(two))
    # 29097904
    print(one == two)
    # True
    print(one is two)
    
    =========================
    3
    32145192
    32145192
    True
    True
    单例模式

     

      __call__

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

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

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

      __len__

    class A:
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __len__(self):
            return len(self.__dict__)
    a = A()
    print(len(a))
    View Code

      __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))
    View Code

      __eq__

    class A:
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __eq__(self,obj):
            if  self.a == obj.a and self.b == obj.b:
                return True
    a = A()
    b = A()
    print(a == b)
    View Code
    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]
    
    deck = FranchDeck()
    print(deck[0])
    from random import choice
    print(choice(deck))
    print(choice(deck))
    纸牌游戏
    ('2', '红心')
    ('7', '红心')
    ('J', '梅花')
    执行结果
    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])
    纸牌游戏2
    [('3', '红心'), ('4', '梅花'), ('A', '方块'), ('K', '黑桃'), ('Q', '红心')]
    执行结果
    class Person:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def __hash__(self):
            return hash(self.name+self.sex)
    
        def __eq__(self, other):
            if self.name == other.name and self.sex == other.sex:return True
    
    
    p_lst = []
    for i in range(84):
        p_lst.append(Person('egon',i,'male'))
    
    print(p_lst)
    print(set(p_lst))
    面试题
    [<__main__.Person object at 0x00000000026F7E48>, <__main__.Person object at 0x00000000026F7F98>, <__main__.Person object at 0x00000000026F7FD0>, <__main__.Person object at 0x0000000002702048>, <__main__.Person object at 0x0000000002702080>, <__main__.Person object at 0x00000000027020B8>, <__main__.Person object at 0x00000000027020F0>, <__main__.Person object at 0x0000000002702128>, <__main__.Person object at 0x0000000002702160>, <__main__.Person object at 0x0000000002702198>, <__main__.Person object at 0x00000000027021D0>, <__main__.Person object at 0x0000000002702208>, <__main__.Person object at 0x0000000002702240>, <__main__.Person object at 0x0000000002702278>, <__main__.Person object at 0x00000000027022B0>, <__main__.Person object at 0x00000000027022E8>, <__main__.Person object at 0x0000000002702320>, <__main__.Person object at 0x0000000002702358>, <__main__.Person object at 0x0000000002702390>, <__main__.Person object at 0x00000000027023C8>, <__main__.Person object at 0x0000000002702400>, <__main__.Person object at 0x0000000002702438>, <__main__.Person object at 0x0000000002702470>, <__main__.Person object at 0x00000000027024A8>, <__main__.Person object at 0x00000000027024E0>, <__main__.Person object at 0x0000000002702518>, <__main__.Person object at 0x0000000002702550>, <__main__.Person object at 0x0000000002702588>, <__main__.Person object at 0x00000000027025C0>, <__main__.Person object at 0x00000000027025F8>, <__main__.Person object at 0x0000000002702630>, <__main__.Person object at 0x0000000002702668>, <__main__.Person object at 0x00000000027026A0>, <__main__.Person object at 0x00000000027026D8>, <__main__.Person object at 0x0000000002702710>, <__main__.Person object at 0x0000000002702748>, <__main__.Person object at 0x0000000002702780>, <__main__.Person object at 0x00000000027027B8>, <__main__.Person object at 0x00000000027027F0>, <__main__.Person object at 0x0000000002702828>, <__main__.Person object at 0x0000000002702860>, <__main__.Person object at 0x0000000002702898>, <__main__.Person object at 0x00000000027028D0>, <__main__.Person object at 0x0000000002702908>, <__main__.Person object at 0x0000000002702940>, <__main__.Person object at 0x0000000002702978>, <__main__.Person object at 0x00000000027029B0>, <__main__.Person object at 0x00000000027029E8>, <__main__.Person object at 0x0000000002702A20>, <__main__.Person object at 0x0000000002702A58>, <__main__.Person object at 0x0000000002702A90>, <__main__.Person object at 0x0000000002702AC8>, <__main__.Person object at 0x0000000002702B00>, <__main__.Person object at 0x0000000002702B38>, <__main__.Person object at 0x0000000002702B70>, <__main__.Person object at 0x0000000002702BA8>, <__main__.Person object at 0x0000000002702BE0>, <__main__.Person object at 0x0000000002702C18>, <__main__.Person object at 0x0000000002702C50>, <__main__.Person object at 0x0000000002702C88>, <__main__.Person object at 0x0000000002702CC0>, <__main__.Person object at 0x0000000002702CF8>, <__main__.Person object at 0x0000000002702D30>, <__main__.Person object at 0x0000000002702D68>, <__main__.Person object at 0x0000000002702DA0>, <__main__.Person object at 0x0000000002702DD8>, <__main__.Person object at 0x0000000002702E10>, <__main__.Person object at 0x0000000002702E48>, <__main__.Person object at 0x0000000002702E80>, <__main__.Person object at 0x0000000002702EB8>, <__main__.Person object at 0x0000000002702EF0>, <__main__.Person object at 0x0000000002702F28>, <__main__.Person object at 0x0000000002702F60>, <__main__.Person object at 0x0000000002702F98>, <__main__.Person object at 0x0000000002702FD0>, <__main__.Person object at 0x0000000002705048>, <__main__.Person object at 0x0000000002705080>, <__main__.Person object at 0x00000000027050B8>, <__main__.Person object at 0x00000000027050F0>, <__main__.Person object at 0x0000000002705128>, <__main__.Person object at 0x0000000002705160>, <__main__.Person object at 0x0000000002705198>, <__main__.Person object at 0x00000000027051D0>, <__main__.Person object at 0x0000000002705208>]
    {<__main__.Person object at 0x00000000026F7E48>}
    执行结果
  • 相关阅读:
    万网中备份数据操作
    《C++ Primer Plus》学习笔记3
    Redhat Linux 下安装Oracle 11g R2
    Android-shareSDK
    jQuery的AJax异步訪问
    swift语言初见
    Num 36 : ZOJ 2100 [ 深度优先搜索算法 ] [ 回溯 ]
    一个点的经度和纬度,以这个点为圆心,1000米为半径,最大的经度和纬度,最小的经度和纬度
    [Swift]LeetCode227. 基本计算器 II | Basic Calculator II
    [Swift]LeetCode225. 用队列实现栈 | Implement Stack using Queues
  • 原文地址:https://www.cnblogs.com/nzd123456/p/9021448.html
Copyright © 2011-2022 走看看