• what's the python之面向对象(进阶)


    面向对象的知识点补充(进阶版)

    classmethod和staticmethod:这两个函数的用途就是可以不用实例化对象就可以调用方法

    class Classmethod_Demo():
        role = 'dog'
    
        @classmethod
        def func(cls):
            print(cls.role)
    
    Classmethod_Demo.func()
    
    
    class Staticmethod_Demo():
        role = 'dog'
    
        @staticmethod
        def func():
            print("当普通方法用")
    
    Staticmethod_Demo.func()

    isinstance和issubclass

      isinstance是用来检查实例化的对象是否是由想检查的类实例化出来的,返回的是布尔值。isinstance(obj,t)

    class Fruit:
        def __init__(self,name):
            self.name=name
    
    class Vegetable:
        def __init__(self,name):
            self.name=name
    
    b=Fruit('banana')
    print(isinstance(b,Fruit))#True
    print(isinstance(b,Vegetable))#False

      issubclass是用来检查一个类是否是想检查的类的子类,返回的是布尔值。issubclass(cls,classinfo)

    class Plant:
        def __init__(self,name):
            self.name=name
    
    class Fruit(Plant):
        def __init__(self,name):
            self.name=name
    
    class Vegetable:
        def __init__(self,name):
            self.name=name
    
    print(issubclass(Fruit,Plant))#True
    print(issubclass(Fruit,Vegetable))#False

    反射

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

    四个可以实现自省的函数:hasattr,getattr,setattr,delattr(后面两个不常用,平时不推荐使用)

    上述四个函数适用于类和对象(一切皆对象,类本身也是一个对象)

    下面用代码来提现每个函数的作用:

    class Sport:
        def __init__(self,name,place):
            self.name=name
            self.place=place
        def play(self):
            print('i like %s'%self.name)
        def where(self):
            print('we play at %s'%self.place)
    
    bas=Sport('basketball','ground')
    #hasattr#查看属性,返回布尔值
    print(hasattr(bas,'name'))#检测是否有属性,输出布尔值
    
    #getattr#得到属性,可以调用方法
    print(getattr(bas,'where'))#检测是否有属性,输出的是方法的内存地址
    n=getattr(bas,'where')
    print(n)#检测是否有属性,与上面一个print里的内容一模一样,输出的是方法的内存地址
    func=getattr(bas,'where')
    func()#调用方法,输出为we play at ground
    # print(getattr(bas,'price'))#不存在即报错
    print(getattr(bas,'price','不存在啊'))#设置默认值即不报错,输出默认值
    
    #setattr可以更改属性,不推荐使用
    setattr(bas,'price',100)#新设置一个属性
    print(bas.price)
    setattr(bas,'show_name',lambda self:self.name+' good')
    print(bas.show_name(bas))#basketball good
    
    #delattr#删除属性,不推荐使用
    delattr(bas,'place')
    # delattr(bas,'name111')#不存在,则报错
    print(bas.__dict__)

    类也是对象,自然也可以使用上述函数:

    class Foo(object):
     
        staticField = "old boy"
     
        def __init__(self):
            self.name = 'alex'
     
        def func(self):
            return 'func'
     
        @staticmethod
        def bar():
            return 'bar'
     
    print getattr(Foo, 'staticField')
    print getattr(Foo, 'func')
    print getattr(Foo, 'bar')

    也可以用来反射当前模块成员:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import sys
    def s1():
        print 's1'
    def s2():
        print 's2'
    
    this_module = sys.modules[__name__]
    hasattr(this_module, 's1')
    getattr(this_module, 's2')

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

    #文件一
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    def test():
        print('from the test')
    
    #文件二
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
     
    """
    程序目录:
        module_test.py
        index.py
     
    当前文件:
        index.py
    """
    
    import module_test as obj
    
    #obj.test()
    
    print(hasattr(obj,'test'))
    
    getattr(obj,'test')()

    以下内容供进阶了解

    __str__、__repr__、__format__、__del__、__call__、__len__、__hash__、__eq__、__item__系列

    改变对象的字符串显示__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))#from repr:  School(oldboy1,北京)
    print('from str: ',str(s1))#from str:  (oldboy1,北京)
    print(s1)#(oldboy1,北京)
    
    '''
    str函数或者print函数--->obj.__str__()
    repr或者交互式解释器--->obj.__repr__()
    如果__str__没有被定义,那么就会使用__repr__来代替输出
    注意:这俩方法的返回值必须是字符串,否则抛出异常
    '''
    print(format(s1,'nat'))#oldboy1-北京-私立
    print(format(s1,'tna'))#私立:oldboy1:北京
    print(format(s1,'tan'))#私立/北京/oldboy1
    print(format(s1,'asfdasdffd'))#oldboy1-北京-私立
    class B:
         def __str__(self):
             return 'str : class B'
    
         def __repr__(self):
             return 'repr : class B'
    
    b=B()
    print('%s'%b)#repr : class B
    print('%r'%b)#str : class B

    __del__

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

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

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

    __call__

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

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

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

    __len__

    相当于内置的len()方法,纯粹检查长度

    class A:
        def __init__(self):
            self.a = 1
            self.b ='b'
    
        def __len__(self):
            return len(self.__dict__)
    a = A()
    print(len(a))#2  其实电泳len方法的时候就是python在内部实现了__len__

    __hash__

    查看是否可以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))#其实调用hash方法的时候就是内部实现了__hash__

    __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)#True

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

    最后给两道大题压压惊

     一、曾经的一道面试题:

    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'))#将84个egon传入列表中
    
    print(p_lst)
    print(set(p_lst))#set是集合,具有去重功能,其实质就是在内部实现了__hash__和__eq__方法

    二、纸牌游戏题:

    from collections import namedtuple
    Cards=namedtuple('Cards',['ranks','suit'])
    class FranchDeck:
        ranks = [str(n) for n in range(2,11)] + list('JQKA')
        suits = ['红心','方板','梅花','黑桃']
    
        def __init__(self):
            self._cards = [Cards(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])#Cards(ranks='2', suit='红心')Cards(ranks='2', suit='红心')
    from random import choice#随机取值,choice依赖于内置的__getitem__
    print(choice(deck))#Cards(ranks='J', suit='黑桃')
    print(choice(deck))#Cards(ranks='2', suit='红心')
    
    from random import shuffle#洗牌,shuffle依赖于__getitem__和__setitem__
    shuffle(deck)
    print(deck[:5])#[Cards(ranks='Q', suit='方板'), Cards(ranks='2', suit='黑桃'), Cards(ranks='5', suit='梅花'), Cards(ranks='4', suit='方板'), Cards(ranks='2', suit='梅花')]
  • 相关阅读:
    Unity3d vector3.forward和transform.forward的区别!
    UGUI实现摇杆
    UGUI实现拼图游戏
    Unity3d打包发布Android程序
    兼容PC和手机触摸代码
    unity3d中Transform组件变量详解
    运算符重载
    扩展方法
    string.Format格式化输出
    网络编程之Socket的TCP协议实现客户端与客户端之间的通信
  • 原文地址:https://www.cnblogs.com/zhuminghui/p/8227893.html
Copyright © 2020-2023  润新知