专栏首页中科院渣渣博肆僧一枚python魔法函数__dict__和__getattr__的妙用

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个键。上面代码简化为:

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • trick(十六)、静态方法、类方法、属性方法

    在类中的方法前面通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法

    于小勇
  • torch.nn.Module

    上述几个属性中,_parameters、_modules和_buffers这三个字典中的键值,都可以通过self.key方式获得,效果等价于self._para...

    于小勇
  • Pytorch预训练模型以及修改

    pytorch中自带几种常用的深度学习网络预训练模型,torchvision.models包中包含alexnet、densenet、inception、resn...

    于小勇
  • python pyqt5 拖拽

    import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.Qt...

    用户5760343
  • Mototrbo TMS 协议分析(数字电台短信协议分析)

    Mototrbo TMS 协议分析 作者:BG7NYT 三年前我就分析出了Mototrbo TMS协议,一直动笔写这篇文章,最近比较闲,就想起了这事。 起初只是...

    netkiller old
  • 原创 | 你会用缓存吗?详解LRU缓存淘汰算法

    大家好,欢迎大家来到周三算法数据结构专题,今天我们和大家聊一个非常常用的算法,叫做LRU。

    TechFlow-承志
  • 在PyTorch中构建高效的自定义数据集

    PyTorch 最近已经出现在我的圈子里,尽管对Keras和TensorFlow感到满意,但我还是不得不尝试一下。令人惊讶的是,我发现它非常令人耳目一新,非常讨...

    磐创AI
  • 爬虫养成记--千军万马来相见(详解多线程)

    本文由图雀社区[1]成员 灿若星空[2] 写作而成,欢迎加入图雀社区,一起创作精彩的免费技术教程,予力编程行业发展。

    一只图雀
  • NHibernate 多对多映射的数据更新

    最近在用 NHibernate 做多对多更新时突然发现 NHibernate 更新的策略很差, 对多对多关系的更新居然是先全部删除再插入全部数据, 感觉非常奇怪...

    beginor
  • Swift版仿“礼物说”的个人界面,一分钟集成不是梦!

    Bison

扫码关注云+社区

领取腾讯云代金券