Python Magic and Builtin Method

构造和初始化

  • __new__用来调用这个类,并返回这个类的实例
  • __init__只是将传入的参数来初始化该实例

控制属性访问

  • __getattr__(self, name):
    当用户视图获取一个不存在的属性时的行为。这适用于对普通拼写错误和重定向,对获取一些不建议的属性时,给予警告或者处理一个AttributeError。只有当调用不存在的属性时,会被返回。

  • __setattr__(self, name, value):
    一个封装的解决方案,无论属性值是否存在,它都允许你定义对属性赋值行为。实现__setattr__要避免无限的递归错误

# uncorrect
def __setattr__(self, name, value):
    self.name = value
    # 没当属性被赋值时,``__setattr__()``会被调用,这样就造成了递归调用。
    # 意味调用``self.__setattrr__('name', value)``,每次方法会调用自己,造成程序崩溃。
    
# correct
def __setattr__(self, name, value):
    self.__dict__[name] = value  # 给类中的属性分配值
    # 定制特有属性
  • __delattr__:
    删除一个属性,实现时要防止无限递归发生

创建自定义容器

Python容器类型:
可变类型: list, dict
不可变类型: stringtuple

  • __len__(self):返回容器长度。
  • __getitem__(self, key):当定义某一项被访问时,使用self[key]所产生的行为。
  • __setitem__(self, key, value):执行self[key] = value,调用该方法。
  • __delitem__(self):定义删除一个项目时的行为,如del self[key]
  • __iter__(self):返回一个容器迭代器。
  • __reversed__(self):实现当 reversed()被调用时的行为。
  • __contains__(self, item):定义调用innot in来测试成员是否在的时候产生的行为。
  • __missing__(self, key)dict类型会有该方法,它定义了key如果在容器中找不到时触发的行为。
class FunctionalList:
    '''实现内置list功能,并丰富一些其他用法'''
    
    def __init__(self, values=None):
        if values is None:
            self.values = []
        else:
            self.values = values
            
    def __len__(self):
        return len(self.values)
        
    def __getitem__(self, key):
        return self.values[key]
        
    def __setitem__(self, key, value):
        return self.values[key] = value
        
    def __delitem__(self, key):
        del self.values[key]

    def __iter__(self):
        return iter(self.values)
        
    def __reversed__(self):
        return FunctionalList(reversed(self.values))
        
    def append(self, value):
        self.values.append(value)
        
    def head(self):
        return self.values[0]
        
    def tail(self):
        return self.values[1:]
        
    def init(self):
        return self.values[:-1]
        
    def last(self):
        return self.values[-1]
        
    def drop(self, n):
        return self.values[n:]
        
    def task(self, n):
        return self.values[:n]

Python collections有很多类似的实现

反射

控制怎么使用内置函数 isinstance()和issubclass()方法,反射定义魔术方法:

  • __instancecheck__(self, instance)
    检查一个实例是不是你定义类的实例
  • __subclasscheck__(self, subclass)
    检查一个类是不是你定义类的子类

可调用对象

特殊的魔术方法可以让类的实例的行为表现像函数一样,可以调用它们,将一个函数当做参数传递到另外一个函数中等。

  • __call__(self, [args,...]):
    允许一个类的实例像函数一样被调用。这意味着x()x.__call__()是相同的。__call__的参数可变,可以定义它为你想要的函数。

__call__在那些类的实例经常改变状态的时候非常有效。调用这个实例是一种改变这个对象状态的直接和优雅的做法。

class Entity:
    '''调用实体来改变实体的位置'''
    
    def __init__(self, size, x, y):
        self.x, self.y = x, y
        self.size = size
        
    def __call__(self, x, y):
        '''改变实体位置'''
        self.x, self.y = x, y

上下文管理器

with声明的代码段中,可以做一些对象的开始操作和退出操作,还能对异常进行处理。需要实现两个魔术方法__enter____exit__

  • __enter__(self):
    定义了当声明with语句的时候,会话管理器在块被初始创建时产生的行为,__enter__的返回值与with语句的目标或者as后的名字绑定。
  • __exit__(self):
    定义了一个代码块被执行或者终止后,会话管理器应该做什么。可以被用来处理异常,执行清理工作或做一些代码块执行完毕后的日常。如果代码块执行成功,exception_type, exception_valuetraceback将为None。否则你可以选择处理这个异常,或者直接交给客户处理。如果你想处理这个异常,请确保__exit__所在的语句结束后返回True。如果你想让异常会话被管理器处理,那就让其产生异常。

创建对象描述器

描述器是通过获取、设置及删除的时候访问的类。描述器并不是独立的,它意味着被一个类所有者持有。当创建面向对象的数据库或者类,里面含有相互依赖的属性时,描述器将会非常有用。一种典型的用法用不同的单位表示数值,或者某个数据的附加属性。
一个描述器类至少应该包括:__get__,__set__,__delete__方法被实现:

  • __get__(self, instance, owner):
    定义描述器的值被取得时候的行为。instance是拥有该描述器对象的实例,owner是拥有者本身。

  • __set__(self, instance, value):
    定义描述器的值被改变时候的行为。instance是拥有该描述器对象的实例,value是要设置的值。

  • __delete__(self, instance):
    定义了描述器值被删除时的行为。instance是拥有该描述器对象的实例

描述器的实例,单位转换

class Meter(object):
    """单位'米'的描述器"""
    
    def __init__(self, value=0.0):
        self.value = float(value)
        
    def __get__(self, instance, owner):
        return self.value
        
    def __set__(self, instance, value):
        self.value = float(value)
        
class Foot(object):
    """单位'尺'的描述器"""
    
    def __get__(self, instance, owner):
        return instance.meter * 3.2808
        
    def __set__(self, instance, value):
        instance.meter = float(value) / 3.2808
        
class Distance(object):
    """用米和英寸表示两个描述器之间的距离"""
    meter = Meter(10)
    foot = Foot()

拷贝

  • __copy__(self):
    调用copy.copy()时产生的行为,返回你的对象的浅拷贝

  • __deepcopy__(self memdict={}):
    调用copy.deepcopy()时产生的行为,返回你的对象的深拷贝。memdict是对之前被拷贝对象的一个缓存----这优化了拷贝过程并且阻止了对递归数据结构拷贝时的无限递归。当你想要进行单独的属性进行拷贝时,调用copy.deepcopy(),并用memdict为第一个参数

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,123评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,031评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,723评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,357评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,412评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,760评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,904评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,672评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,118评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,456评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,599评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,264评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,857评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,731评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,956评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,286评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,465评论 2 348

推荐阅读更多精彩内容