• python魔法函数__dict__和__getattr__的妙用


    python魔法函数__dict__和__getattr__的妙用

    _dict_

    __dict__是用来存储对象属性的一个字典,其键为属性名,值为属性的值。

    既然__dict__是个字典那么我们就可以用字典的属性了。

    我们通过使用dir()属性来看看__dict__都有哪些属性。

    ['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
    

    我们看一段代码内含注释:

    class A():
        def __init__(self):
            self.name="liming"
    
        def save_data(self,dicts):
            self.__dict__.update(dicts)#添加字典元素
            if isinstance(self.__dict__,dict):
                print(True)
            #获取字典独有的属性
            print(set(dir(self.__dict__))-set(dir(self)))
            return self.__dict__
    
    if __name__ == '__main__':
         dicts={"a":1,"b":2,"c":3}
         a=A()
         print(a.save_data(dicts))
    

    输出结果

    True
    {'__delitem__', 'keys', 'update', '__len__', '__getitem__', 'get', 'clear', 'copy', 'popitem', '__iter__', 'items', '__contains__', 'pop', '__setitem__', 'fromkeys', 'values', 'setdefault'}
    {'name': 'liming', 'a': 1, 'b': 2, 'c': 3}
    

    下面来一个比较实用的例子来大大的减少你的代码,做到真正的pythonic。
    我们在使用给对象的属性赋值的时候

    class A():
        def __init__(self,dicts):
            self.name=dicts["name"]
            self.age=dicts["age"]
            self.sex=dicts["sex"]
            self.hobby=dicts["hobby"]
    if __name__ == '__main__':
         dicts={"name":"lisa","age":23,"sex":"women","hobby":"hardstyle"}
         a=A(dicts)
    

    我们看到我们需要换取传入的字典的各个键值,并创建键值同名一个属性,这里我们只有4个还好,想象一下如果我们传入的字典有100个键。。。如何还是这样一个一个赋值不敢想不敢想,人家都写完代码了,你还在赋值有木有。。
    其实一开始的那段代码已经给出了答案,如果不会也没关系,
    下面我们就来点pythonic的python。来解决这个问题。
    上面代码简化为:

    class A():
        def __init__(self,dicts):
            self.__dict__.update(dicts)
            print(self.__dict__)
    
    if __name__ == '__main__':
         dicts={"name":"lisa","age":23,"sex":"women","hobby":"hardstyle"}
         a=A(dicts)
    

    看完后感觉怎么样啊,其实__dict__还有一个重要的用处就是单例模式中共享同一状态,参考之前写的单例模式。
    拓展:部分内建函数不包含__dict__属性比如list,如果要查看list的属性怎么办呢,这时候用dir(list),dir方法也是查看对象的属性,包括内建对象的属性,但是它的输出形式列表,而__dict__是列表。

    _getattr_

    经过查阅资料用我的理解去解释这个方法的用法那就是:使用.获取属性的时候,如果该属性存在就输出其值,如果不存在则会去找_getatrr_,我们可以通过重写该方法可以实现动态属性的操作。(如果只允许添加指定的属性需要用__solts__函数控制,这里不做详细讲解)

    先来一段比较有意思的代码

    from requests_html import HTMLSession
    class UrlGenerator(object):
        def __init__(self, root_url):
            self.url = root_url
            self.session=HTMLSession()
    
        def __getattr__(self, item):
            if item == 'get':
                self.get_html()
            return UrlGenerator('{}.{}'.format(self.url, item))
        def get_html(self):
            req = self.session.get(self.url)
            print(req.text)
    
    url_gen = UrlGenerator('https://www')
    url_gen.baidu.com.get
    

    充分利用__getattr__会在没有查找到相应实例属性时被调用的特点,方便的通过链式调用生成对应的url,在碰到get方法的时候调用函数获取其网页源码。
    可调用的对象更加的优雅,链式的操作不仅优雅而且还能很好的说明调用的接口的意义。

    下面展示一个__getattr__经典应用的例子,可以通过获取属性值的方式获取字典的键值。

    class ObjectDict(dict):
        def __init__(self, *args, **kwargs):
            super(ObjectDict, self).__init__(*args, **kwargs)
    
        def __getattr__(self, name):
            value = self[name]
            if isinstance(value, dict):
                value = ObjectDict(value)
            return value
    
    if __name__ == '__main__':
        od = ObjectDict(asf={'a': 1}, d=True)
        print(od.asf,od.asf.a)     # {'a': 1} 1
        print(od.d)                 # True
    

    好了,今天的内容就到这。

  • 相关阅读:
    The library contains native libr…
    DHCP configurations in Ubuntu
    如何编译Linux Kernel
    Rsync 使用指南
    Linux下用semaphore来做进程间互斥
    How to generate patch file?
    PS3MediaServer(用于PS3的DLNA server) 在Ubuntu 9.10上的安装和配置
    嘉猪的最爱 PS3
    梦寐以求的SPL总冠军,KT你赢了
    PLU space in 优酷
  • 原文地址:https://www.cnblogs.com/c-x-a/p/9475724.html
Copyright © 2020-2023  润新知