python黑魔法 -- 内置方法使用
很多pythonic的代码都会用到内置方法,根据自己的经验,罗列一下自己知道的内置方法。
__getitem__ __setitem__ __delitem__
这三个方法是字典类的内置方法,分别对应于查找、设置、删除操作,以一个简单的例子说明:
class A(dict):
def __getitem__(self, key):
print '__getitem__'
return super(A, self).__getitem__(key)
def __setitem__(self, key, value):
print '__setitem__'
return super(A, self).__setitem__(key, value)
def __delitem__(self, key):
print '__delitem__'
return super(A, self).__delitem__(key)
a = A()
a[1] = 1
b = a[1]
del a[1]
a.get(1)
上面的代码中a[1] = 1实际上调用的就是a.__setitem__(1, 1), a[1]调用的是a.__get__item__(1), del a[1]调用的是a.__setitem__(1)。需要注意的是,字典示例的get方法和__getitem__方法不存在调用关系,两者互不影响。
__getattribute__ __getattr__ __setattr__ __delattr__
__getattribute__和__getattr__都是从python对象示例中获取成员变量的方法,差别在于__getattribute__在任何时候都会调用,而__getattr__只有在__getattribute__执行完成之后并且没有找到成员变量的时候才会执行。__setattr__在给成员变量赋值的时候调用,__delattr__在回收成员变量的时候调用,一下面的例子说明:
class A(object):
x = []
def __getattribute__(self, name):
print '__getattribute__'
return super(A, self).__getattribute__(name)
def __setattr__(self, key, value):
print '__setattr__'
return super(A, self).__setattr__(key, value)
def __getattr__(self, item):
print '__getattr__'
def __delattr__(self, item):
print '__delattr__'
return super(A, self).__delattr__(item)
a = A()
a.x
a.y
b = getattr(a, 'x')
b = getattr(a, 'y')
a.x = 1
a.y = 1
setattr(a, 'x', 1)
setattr(a, 'y', 1)
del a.x
del a.y
因为x是a的成员变量,a.x会调用a.__getattribue__('x'),而y不是a的成员变量,在调用a.__getattribue__('y')之后还会调用a.__getattr__('y'),内置方法getattr也是按照此顺序调用,唯一的区别在于getattr在成员变量不存在的时候不会抛出异常,而是给一个默认值。a.x = 1和setattr(a, 'x', 1)都会调用a.__setattr__('x', 1),如果原来的成员变量不存在,__setattr__会给实例增加一个成员变量,而不是抛出异常。
__call__
如果重载了__call__方法,则实例对象就可以像方法一样调用了。如果实例a的类实现了这个方法,那么a(*args, **kwargs)就会调用a.__call__(*args, **kwargs)。用这种方法可以简单方便的实现装饰器,如下所示:
class A(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print '__call__'
return self.func(*args, **kwargs)
@A
def foo(x):
return x
foo(1)
装饰器语法糖相当于foo = A(foo), 和闭包不同,foo已经不是一个函数而是类A的实例。foo(1)会执行foo.__call__(1)。当然这个例子实现的装饰器并不好,会改变foo的函数签名,而且也不能装饰类方法。
此外元类的__call__也可以控制实例的创建过程,因为当类创建对象时,元类的__call__函数就被调用,进而调用type.__call__创建对象,type.__call__回依次调用类的__new__和__init__生成实例。以单例模式为例:
class Singleton(type):
def __call__(cls, *args):
print "Singleton call"
if not hasattr(cls, 'instance'):
cls.instance = super(Singleton, cls).__call__(*args)
return cls.instance
class Cache(object):
__metaclass__ = Singleton
def __new__(cls, *args):
print "Cache new"
return object.__new__(cls, *args)
def __init__(cls, *args, **kwargs):
print "Cache init"
a = Cache()
b = Cache()
print a is b
__get__ __set__
这三个方法分别对应于描述器的查询、设置、删除函数,还是以一个简单的例子来说明:
class A(object):
def __get__(self, instance, owner):
print '__get__'
def __set__(self, instance, value):
print '__set__'
class B(object):
a = A()
b = B()
c = b.a
b.a = 1
类A的示例a作为b的成员变量时候,访问示例b中成员变量a的时候会调用a.__get__(b, B),修改b中成员变量a的时候会调用a.__set__(b, 1)。需要注意的是,当用B.a访问的时候参数instance为None。实际上像classmethod,staticmethod这样的装饰器都是通过装饰器来实现的,通过装饰器就可以解决上面不能作为类方法装饰器的问题。
import types
class Profiled(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
return self.func(*args, **kwargs)
def __get__(self, instance, owner):
if instance is None:
return self
else:
return types.MethodType(self, instance)
class Spam(object):
@Profiled
def bar(self, x):
return x + 1
s = Spam()
print s.bar(5)
在__get__方法中,不是Spam.bar调用,则instance不为None的情况下,会用types.MethodType把bar和s做一个绑定,s.bar(5)等价于执行了bar.__get__(s, Spam).__call__(5),看起来很绕,但实际上用起来很方便。
python黑魔法 -- 内置方法使用的更多相关文章
- python 字典内置方法get应用
python字典内置方法get应用,如果我们需要获取字典值的话,我们有两种方法,一个是通过dict['key'],另外一个就是dict.get()方法. 今天给大家分享的就是字典的get()方法. 这 ...
- Python的内置方法,abs,all,any,basestring,bin,bool,bytearray,callable,chr,cmp,complex,divmod
Python的内置方法 abs(X):返回一个数的绝对值,X可以是一个整数,长整型,或者浮点数,如果X是一个复数,此方法返回此复数的绝对值(此复数与它的共轭复数的乘积的平方根) >>> ...
- 7.python字符串-内置方法分析
上篇对python中的字符串内置方法进行了列举和简单说明,但这些方法太多,逐一背下效率实在太低,下面我来对这些方法按照其功能进行总结: 1.字母大小写相关(中文无效) 1.1 S.upper() -& ...
- 6.python字符串-内置方法列举
所谓内置方法,就是凡是字符串都能用的方法,这个方法在创建字符串的类中,下面是总结: 首先,我们要学习一个获取帮助的内置函数 help(对象) ,对象可以是一个我们创建出来的,也可以是创建对象的那个类, ...
- python字符串-内置方法列举
所谓内置方法,就是凡是字符串都能用的方法,这个方法在创建字符串的类中,下面是总结: 首先,我们要学习一个获取帮助的内置函数 help(对象) ,对象可以是一个我们创建出来的,也可以是创建对象的那个类, ...
- python字符串内置方法
网上已经有很多,自己操作一遍,加深印象. dir dir会返回一个内置方法与属性列表,用字符串'a,b,cdefg'测试一下 dir('a,b,cdefg') 得到一个列表 ['__add__', ' ...
- Python的内置方法
一 isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object) ...
- Python字典内置方法
Python字典包含了以下内置方法: 序号 函数及描述 1 radiansdict.clear()删除字典内所有元素 2 radiansdict.copy()返回一个字典的浅复制 3 radiansd ...
- python数据类型内置方法
内容概要 列表内置方法 字典内置方法 字符串转换成字典的方法 eval() 元组内置方法 元组相关笔试题 集合内置方法 列表内置方法 l1 = [2, 4, 5, 7, 3, 9, 0, 6] # 升 ...
随机推荐
- In-Memory:内存数据库
在逝去的2016后半年,由于项目需要支持数据的快速更新和多用户的高并发负载,我试水SQL Server 2016的In-Memory OLTP,创建内存数据库实现项目的负载需求,现在项目接近尾声,系统 ...
- 启动了VSAN服务的主机不在vCenter集群中
背景: 这个问题的来源是,某用户将该ESXi主机直接夺取到另一个vCenterA的管辖中,而这个vCenterA中集群A开启了VSAN功能,导致再次反向夺取到vCenterB中的时候带有了来自于集群A ...
- Spring之旅
Java使得以模块化构建复杂应用系统成为可能,它为Applet而来,但为组件化而留. Spring是一个开源的框架,最早由Rod Johnson创建.Spring是为了解决企业级应用开发的复杂性而创建 ...
- JS的内建函数reduce
@(js) reduce函数,是ECMAScript5规范中出现的数组方法.在平时的工作中,相信大家使用的场景并不多,一般而言,可以通过reduce方法实现的逻辑都可以通过forEach方法来变相的实 ...
- 就这么漂来漂去---一个毕业三个月的java程序员的裸辞风波
注:这并不是一篇技术文章,而是记录了我这几个月经历的入职,裸辞,找工作的心路历程,简单介绍一个博主的情况,我是16年毕业生,校招进了一家北京的公司,java开发,和很多年轻人一样,干了一段时间,我发现 ...
- 模仿Linux内核kfifo实现的循环缓存
想实现个循环缓冲区(Circular Buffer),搜了些资料多数是基于循环队列的实现方式.使用一个变量存放缓冲区中的数据长度或者空出来一个空间来判断缓冲区是否满了.偶然间看到分析Linux内核的循 ...
- 访问者模式(visitorpattern)
/** * 访问者模式 * @author TMAC-J * 在客户端和元素之间添加一个访问者 * 当你需要添加一些和元素关系不大的需求时,可以直接放在访问者里面 * 或者是元素之间有一些公共的代码块 ...
- java springMVC SSM 操作日志 4级别联动 文件管理 头像编辑 shiro redis
A 调用摄像头拍照,自定义裁剪编辑头像 B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,开发利器)+快速构建表单; 技术:313596790freemaker模版技术 ,0个代码不用写 ...
- iOS 后台处理
iOS 后台处理的常见用途 1.进入后台时候删除资源:应用处于挂起状态的时候所占用的资源越少,该应用被iOS终止的风险就越低.通过从内存中清理那些易于重新创建的资源,可以增加应用驻留内存的机会,因此可 ...
- Java企业实训 - 01 - Java前奏
前言: 虽然个人专攻.NET方向,不过由于个人是干教育行业的,方方面面的东西,不能说都必须精通,但肯定多少都会涉及到. 一个菜鸟学员,从啥都不会,经过一步步学习,最后到企业上手掌管一个模块甚至一个项目 ...