很多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 = 1setattr(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黑魔法 -- 内置方法使用的更多相关文章

  1. python 字典内置方法get应用

    python字典内置方法get应用,如果我们需要获取字典值的话,我们有两种方法,一个是通过dict['key'],另外一个就是dict.get()方法. 今天给大家分享的就是字典的get()方法. 这 ...

  2. Python的内置方法,abs,all,any,basestring,bin,bool,bytearray,callable,chr,cmp,complex,divmod

    Python的内置方法 abs(X):返回一个数的绝对值,X可以是一个整数,长整型,或者浮点数,如果X是一个复数,此方法返回此复数的绝对值(此复数与它的共轭复数的乘积的平方根) >>> ...

  3. 7.python字符串-内置方法分析

    上篇对python中的字符串内置方法进行了列举和简单说明,但这些方法太多,逐一背下效率实在太低,下面我来对这些方法按照其功能进行总结: 1.字母大小写相关(中文无效) 1.1 S.upper() -& ...

  4. 6.python字符串-内置方法列举

    所谓内置方法,就是凡是字符串都能用的方法,这个方法在创建字符串的类中,下面是总结: 首先,我们要学习一个获取帮助的内置函数 help(对象) ,对象可以是一个我们创建出来的,也可以是创建对象的那个类, ...

  5. python字符串-内置方法列举

    所谓内置方法,就是凡是字符串都能用的方法,这个方法在创建字符串的类中,下面是总结: 首先,我们要学习一个获取帮助的内置函数 help(对象) ,对象可以是一个我们创建出来的,也可以是创建对象的那个类, ...

  6. python字符串内置方法

    网上已经有很多,自己操作一遍,加深印象. dir dir会返回一个内置方法与属性列表,用字符串'a,b,cdefg'测试一下 dir('a,b,cdefg') 得到一个列表 ['__add__', ' ...

  7. Python的内置方法

    一 isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object) ...

  8. Python字典内置方法

    Python字典包含了以下内置方法: 序号 函数及描述 1 radiansdict.clear()删除字典内所有元素 2 radiansdict.copy()返回一个字典的浅复制 3 radiansd ...

  9. python数据类型内置方法

    内容概要 列表内置方法 字典内置方法 字符串转换成字典的方法 eval() 元组内置方法 元组相关笔试题 集合内置方法 列表内置方法 l1 = [2, 4, 5, 7, 3, 9, 0, 6] # 升 ...

随机推荐

  1. 在离线环境中使用.NET Core

    在离线环境中使用.NET Core 0x00 写在开始 很早开始就对.NET Core比较关注,一改微软之前给人的印象,变得轻量.开源.跨平台.最近打算试着在工作中使用.但工作是在与互联网完全隔离的网 ...

  2. 由Dapper QueryMultiple 返回数据的问题得出==》Dapper QueryMultiple并不会帮我们识别多个返回值的顺序

    异常汇总:http://www.cnblogs.com/dunitian/p/4523006.html#dapper 今天帮群友整理Dapper基础教程的时候手脚快了点,然后遇到了一个小问题,Dapp ...

  3. 使用mybatis-generator在自动生成Model类和Mapper文件

    使用mybatis-generator插件可以很轻松的实现mybatis的逆向工程,即,能通过表结构自动生成对应的java类及mapper文件,可以大大提高工作效率,并且它提供了很多自定义的设置可以应 ...

  4. MySQL 系列(二) 你不知道的数据库操作

    第一篇:MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:MySQL 系列(二) 你不知道的数据库操作 本章内容: 查看\创建\使用\删除 数据库 用户管理及授权实战 局域网 ...

  5. SpringMVC+Shiro权限管理【转】

    1.权限的简单描述 2.实例表结构及内容及POJO 3.Shiro-pom.xml 4.Shiro-web.xml 5.Shiro-MyShiro-权限认证,登录认证层 6.Shiro-applica ...

  6. Android 调用百度地图API

    一.到 百度地图开发平台下载SDK http://lbsyun.baidu.com/index.php?title=androidsdk/sdkandev-download 1.点击自定义下载 2.下 ...

  7. Android之网络数据存储

    一.网络保存数据介绍 可以使用网络来保存数据,在需要的时候从网络上获取数据,进而显示在App中. 用网络保存数据的方法有很多种,对于不同的网络数据采用不同的上传与获取方法. 本文利用LeanCloud ...

  8. Android Studio:Failed to resolve ***

    更换电脑后,也更新了所有的SDK的tool,仍然报错:Failed to resolve  各种jar包,出现这种问题主要是因为在Android studio中默认不允许在线更新,修改方法如下:

  9. 超详细mysql left join,right join,inner join用法分析

    下面是例子分析表A记录如下: aID        aNum 1           a20050111 2           a20050112 3           a20050113 4   ...

  10. php利用root权限执行shell脚本

    vi /etc/sudoers , 为apache用户赋予root权限,并且不需要密码,还有一步重要的修改(我被困扰的就是这个地方) root  ALL=(ALL)  ALL apache  ALL= ...