竞争无处不在,青春永不言败!专业撸代码,副业修bug

Talk is cheap , show me the code!



python 内建函数专题

all 用来控制 import , 甚至可以改变 _private 为 public
enter , exit 用于上下文管理器
iter 用于迭代器
repr 给计算机读, str ==》 str 给人读
len ==》 len

obj:
['__class__',
 '__delattr__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__le__',
 '__lt__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__']

重写 +


>>> class Number(object):

... def __init__(self,value):
... self.value = value
... def __add__(self,other):
... return self.value+other.value
...
>>> Number(3)+Number(4)
7

实现类似字典操作

>>> class A(dict):
...     def __getitem__(self,key):
...         return super(A,self).__getitem__(key)
...     def __setitem__(self,key,value):
...         return super(A,self).__setitem__(key,value)
...     def __delitem__(self,key):
...         return super(A,self).__delitem__(key)
...
>>> a = A()
>>> a['name'] = 'Frank'
>>> a['age'] = 18
>>> print('name: {}\nage:{}'.format(a['name'],str(a['age'])))

实现getattr , setattr , del b.x 方法

>>> class B(object):
...     x = []
...     def __getattribute__(self,name):
...         return super(B,self).__getattribute__(name)
...     def __setattribute__(self,name,value):
...         return super(B,self).__setattribute__(name,value)
...     def __delattribute__(self,item):
...         return super(B,self).__delattribute__(item)
...
>>> b = B()
>>> b.x
[]
>>> getattr(b,'x')
[]
>>> b.x = 1
>>> getattr(b,'x')
1
>>> setattr(b,'y','2')
>>> b.y
'2'

>>> del b.y

原文如下:

很多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),看起来很绕,但实际上用起来很方便。

posted @ 2018-07-03 17:23  云雾散人  阅读(197)  评论(0编辑  收藏  举报

Your attitude not your aptitude will determine your altitude!

如果有来生,一个人去远行,看不同的风景,感受生命的活力!