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

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

python魔法函数__dict__和__getattr__的妙用的更多相关文章

  1. python魔法函数之__getattr__与__getattribute__

    getattr 在访问对象的属性不存在时,调用__getattr__,如果没有定义该魔法函数会报错 class Test: def __init__(self, name, age): self.na ...

  2. Python魔法函数

    python中定义的以__开头和结尾的的函数.可以随意定制类的特性.魔法函数定义好之后一般不需要我们自己去调用,而是解释器会自动帮我们调用. __getitem__(self, item) 将类编程一 ...

  3. python魔法函数(二)之__getitem__、__len__、__iter__

    魔法函数会增强python类的类型,独立存在 __getitem class Company: def __init__(self, employees): self.employees = empl ...

  4. Python魔法函数与两比特量子系统模拟

    技术背景 本文主要涵盖两个领域的知识点:python的魔法函数和量子计算模拟,我们可以通过一个实际的案例来先审视一下这两个需求是如何被结合起来的. 量子计算模拟背景 ProjectQ是一个非常优雅的开 ...

  5. python魔法函数的一些疑问

    看了魔法函数,有一点疑问.1中需要用self.word才能执行,而2直接用self就可以执行.而1中Word继承了int基本类型,但在__new__时并没有什么卵用.当用 Word(“123”)来实例 ...

  6. python 进阶读书笔记2 -- python魔法函数

    #!/usr/bin/env python# -*- coding: utf-8 -*- class student: def __init__(self, name_list): self.stud ...

  7. raindi python魔法函数(一)之__repr__与__str__

    __repr__和__str__都是python中的特殊方法,都是用来输出实例对象的,如果没有定义这两个方法在打印的时候只会输出实例所在的内存地址 这种方式的输出没有可读性,并不能直观的体现实例.py ...

  8. Python的魔法函数系列 __getattrbute__和__getattr__

      #!/usr/bin/env python # -*- coding: utf-8 -*- import sys __metaclass__ = type """ _ ...

  9. python面向对象的多态-类相关内置函数-类内置魔法函数-迭代器协议-上下文管理-04

    多态 一种事物具备不同的形态 例如:水 --> 固态.液态.气态 多态:# 多个不同对象可以相应同一个对象,产生不同的结果 首先强调,多态不是一种特殊的语法,而是一种状态,特性(多个不同对象可以 ...

随机推荐

  1. bzoj3622-已经没有什么好害怕的的了

    题意 给出两个长度为 \(n\) 的数列 \(a,b\) ,\(2n\) 个数都互不相同,求有多少种对应方式使得 \(a_i>b_i\) 的个数比 \(a_i<b_i\) 的个数恰好多 \ ...

  2. bzoj2669-局部极小值

    题意 有一个 \(n\times m\) 的矩阵,其中每个数都是 \([1,n\times m]\) 中的一个,不会重复.有一些地方的值比周围的8个位置都小(如果有的话).给出这些位置,求这样的矩阵有 ...

  3. FTP安装

    FTP 一.安装,挂第3张光驱 1.挂盘 2.进入cdrom中,路径:cd /mnt/cdrom 3.进入RPMS中,路径:cd /mnt/cdrom/RedHat/RPMS 4.查看版本为:vsft ...

  4. [十四]SpringBoot 之 Spring拦截器(HandlerInterceptor)

    过滤器属于Servlet范畴的API,与spring 没什么关系. Web开发中,我们除了使用 Filter 来过滤请web求外,还可以使用Spring提供的HandlerInterceptor(拦截 ...

  5. 深入理解JVM一类加载器原理

    我们知道我们编写的java代码,会经过编译器编译成字节码文件(class文件),再把字节码文件装载到JVM中,映射到各个内存区域中,我们的程序就可以在内存中运行了.那么字节码文件是怎样装载到JVM中的 ...

  6. 【BZOJ4200】【NOI2015】小园丁与老司机(动态规划,网络流)

    [BZOJ4200][NOI2015]小园丁与老司机(动态规划,网络流) 题面 BZOJ权限题,洛谷链接 题解 一道二合一的题目 考虑第一问. 先考虑如何计算六个方向上的第一个点. 左右上很好考虑,只 ...

  7. listen() 函数

    声明:本文来自网络博文的合并,文后有链接. 一.listen函数仅由TCP服务器调用 它做两件事: 1.当socket函数创建一个套接字时,它被假设为一个主动套接字,也就是说,它是一个将调用conne ...

  8. 【数学】【背包】【NOIP2018】P5020 货币系统

    传送门 Description 在网友的国度中共有 \(n\) 种不同面额的货币,第 \(i\) 种货币的面额为 \(a[i]\),你可以假设每一种货币都有无穷多张.为了方便,我们把货币种数为 \(n ...

  9. 【极值问题】【CF33C】 Wonderful Randomized Sum

    传送门 Description 给你一个数列\(A\),你可以选择任意一个前缀和任意一个后缀,前缀后缀可重合.给他们乘\(-1\).求最大能获得的序列和. Input 第一行是一个数\(n\)代表数列 ...

  10. python 常用 time, datetime处理

    python 中 time 有三种格式: float, struct tuple(time.struct_time 或 datetime.datetime), str 常用的: float --> ...