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] # 升 ...
随机推荐
- [原] KVM 虚拟化原理探究(1)— overview
KVM 虚拟化原理探究- overview 标签(空格分隔): KVM 写在前面的话 本文不介绍kvm和qemu的基本安装操作,希望读者具有一定的KVM实践经验.同时希望借此系列博客,能够对KVM底层 ...
- 在 SAE 上部署 ThinkPHP 5.0 RC4
缘起 SAE 和其他的平台有些不同,不能在服务器上运行 Composer 来安装各种包,必须把源码都提交上去.一般的做法,可能是直接把源码的所有文件复制到目录中,添加到版本库.不过,这样就失去了与上游 ...
- C++中的const
一,C++中const的基本知识 1.C++中const的基本概念 1.const是定义常量的关键字,表示只读,不可以修改. 2.const在定义常量的时候必须要初始化,否则报错,因为常量无法修改,只 ...
- EventBus实现activity跟fragment交互数据
最近老是听到技术群里面有人提出需求,activity跟fragment交互数据,或者从一个activity跳转到另外一个activity的fragment,所以我给大家介绍一个开源项目,EventBu ...
- 【Web动画】SVG 实现复杂线条动画
在上一篇文章中,我们初步实现了一些利用基本图形就能完成的线条动画: [Web动画]SVG 线条动画入门 当然,事物都是朝着熵增焓减的方向发展的,复杂线条也肯定比有序线条要多. 很多时候,我们无法人工去 ...
- 记录我这一年的技术之路(nodejs纯干货)
2015年12月28日23:19:54 更新koa应用.学习型网站和开发者工具等 coding伊始 开始认认真真的学习技术还是2015.10.21日开始的,记得很清楚,那天,是我在龙湖正式学习的第一天 ...
- EntityFramework.Extended 支持 MySql
EntityFramework.Extended 默认不支持 MySql,需要配置如下代码: [DbConfigurationType(typeof(DbContextConfiguration))] ...
- 在centos7上安装ClamAV杀毒,并杀毒(centos随机英文10字母)成功
前言 上传文件的时候发现总是失败,查看top发现有个进程一直cpu占用80%以上,而且名称还是随机数.kill之后,一会儿又重新生成了.突然发现居然没有在服务端杀毒的经历.在此处补齐. 安装clama ...
- Html.DropDownLis绑定数据库
效果: 方法一: View: <div class="col-md-md-4"> <div class="input-group"> & ...
- CommandPattern
/** * 命令模式 * @author TMAC-J * 将调用者和接受者分离 * 可以将一组命令组合在一起,适合很多命令的时候 */ public class CommandPattern { i ...