码迷,mamicode.com
首页 > 其他好文 > 详细

魔术方法1

时间:2017-11-19 19:47:26      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:typeerror   特殊   instance   dict   app   运算   last   ota   它的   

# 特殊属性:
        __name__   类、方法等名字
        __module__  类定义所在的模块名
        __class__  对象或类所属的类
        __bases__  类的基类的元组,顺序为它们在基类列表出现的顺序
        __doc__   类、方法的文档字符串,没有定义默认为None
        __mro__   类的moro,class.mro()返回的结果保存在__mro__中
        __dict__  类或实例的属性,可写的字典

# 查看属性:
    __dir__:
        返回类或者对象的所有成员名称列表。dir()函数就是调用__dir__()。如果提供
    __dir__(),则返回属性的列表,否则会尽量从__dict__属性中收集信息。
    
    如果dir([obj])参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息
    dir()对于不同类型的对象具有不同的行为:
        如果对象是模块对象,列表包含模块的属性名。
        如果对象是类型或者类对象,列表包含类的属性名,及它的基类的属性名
        否则列表包含对象的属性名,它的类的属性名和类的基类的属性名。


```python
class Foo:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def show(self):
        return self.age
x = Foo(‘z‘,12)
x.show()
print(Foo.__name__)

def fn(x):
    return fn(x-1)+fn(x-2)
fn(5)
```

    Foo
    


    ---------------------------------------------------------------------------

    RecursionError                            Traceback (most recent call last)

    <ipython-input-6-121340e7e479> in <module>()
         11 def fn(x):
         12     return fn(x-1)+fn(x-2)
    ---> 13 fn(5)
    

    <ipython-input-6-121340e7e479> in fn(x)
         10 
         11 def fn(x):
    ---> 12     return fn(x-1)+fn(x-2)
         13 fn(5)
    

    ... last 1 frames repeated, from the frame below ...
    

    <ipython-input-6-121340e7e479> in fn(x)
         10 
         11 def fn(x):
    ---> 12     return fn(x-1)+fn(x-2)
         13 fn(5)
    

    RecursionError: maximum recursion depth exceeded


# 魔术方法:
    分类:
        1.创建与销毁  __init__ 与 __del__
        2.hash
        3.bool
        4.可视化
        5.运算符重载
        6.容器和大小
        7.可调用对象
        8.上下文管理
        9.反射
        10.描述器
        11.其他


```python
"""
    1.__hash__ 内建函数hash()调用的返回值,返回一个整数,如果定义这个方法该类的实例就可hash
"""
class A:
    def __init__(self):
        self.a = ‘a‘
        self.b = ‘b‘
    def __hash__(self):
        return 1
    def __eq__(self, other):
        return self.a == other.a
print(hash(A()))
print((A(),A()))
print({A(),A()})
s = {A(),A()}
print(s)
```

    1
    (<__main__.A object at 0x000001A2B6A2BD30>, <__main__.A object at 0x000001A2B6A2BAC8>)
    {<__main__.A object at 0x000001A2B6A2BB38>}
    {<__main__.A object at 0x000001A2B6A2BD30>}
    

# \__eq\__ 
    __eq__ 对应==操作符,判断2个对象是否相等,返回bool值
    __hash__方法返回一个hash值作为set的key,但是去重,还需要__eq__来判断2个对象
    是否相等
    hash值相等,只是hash冲突,不能说明两个对象是相等的。
    一般提供__hash__方法是为了作为set或者dict的key的,所以去重 要同时提供__eq__方法
    可hash对象必须提供__hash__方法,没有提供的话,isinstance(p1,collections.Hashable)
    一定为false
    __hash__方法返回一个hash值作为set的key,但是去重,还需要__eq__来判断2个对象
    是否相等
    hash值相等,只是hash冲突,不能说明两个对象是相等的。
    一般提供__hash__方法是为了作为set或者dict的key的,所以去重 要同时提供__eq__方法
    可hash对象必须提供__hash__方法,没有提供的话,isinstance(p1,collections.Hashable)
    一定为false

# list类不可hash:
    在list类源码中,有一句__hash__ = None,也就是如果调用__hash__()相当于None()
    一定报错,。
    所有类都继承object,而这个类是具有__hash__()方法 ,如果一个类不能被hash,就是
    把__hash__设置为None了。


```python
from collections import Hashable

class Point:
    def __init__(self, x ,y):
        self.x = x
        self.y = y
    
    def __hash__(self):
        return hash((self.x, self.y))
    
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

p1 = Point(4,5)
p2 = Point(4,5)
print(hash(p1))
print(hash(p2))

print(p1 is p2)
print(p1 == p2)c
print(set((p1, p2)))

print(isinstance(p1, Hashable))
```

    3713084879518070856
    3713084879518070856
    False
    True
    {<__main__.Point object at 0x000001A2B6AE3898>}
    True
    

# bool
    __bool__  内建函数,或者对象放在逻辑表达式的位置,调用这个函数返回布尔值,
    没有定义__bool__(),就找__len__()返回长度,非0为真。如果__len__()也没有定义,那么所有实例返回真


```python
class A:
    pass
print(bool(A()))

class B:
    def __bool__(self):
        return False
print(bool(B))#类
print(bool((B())))#实例

class C:
    def __len__(self):
        return 0
print(bool(C()))
```

    True
    True
    False
    False
    

# 可视化
    __repr__ 内建函数rer()对一个对象获取字符串表达。如果一个类定义了__repr__()但没有定义__str__,那么在请求该类的实例的‘非正式‘的字符串也将调用__repr__()
    __str__ str()函数,内建函数format、print()函数调用,需要返回对象的字符串表达
    __bytes__  bytes的时候,返回一个对象的bytes表达,即返回Bytes对象


```python
class A:
    def __init__(self):
        self.a = ‘a‘
        self.b = ‘b‘
    def __repr__(self):
        return ‘repr: {}, {}‘.format(self.a, self.b)
    def __str__(self):
        return ‘str:    {}, {}‘.format(self.a, self.b)
print(A())
print([A()])
print(([str(A())]))
print(‘str:a,b‘)
s = ‘b‘
print([‘a‘], (s,))
```

    str:    a, b
    [repr: a, b]
    [‘str:    a, b‘]
    str:a,b
    [‘a‘] (‘b‘,)
    

# 运算符重载






```python
‘实例的减法‘
class A:
    def __init__(self, x):
        self.x = x
    def __sub__(self, other):#减法
        return self.x - other.x
    def __ne__(self, other):
        return self.x != other.x
    def __eq__(self, other):
        return self.x == other.x
a1 = A(4)
a2 = A(4)
a1-a2 # 等价于 a1.__sub__(a2)
print(a1 == a2)
print(a1 != a2)
```

    True
    False
    


```python
class Point:
    """
        __sub__ 相等
        __add__ 相加
        __str__ 格式化字符串
    """
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __eq__(self, other):
        return self.x == self.x and self.y == self.y
    
    def __add__(self, other):
        return (self.x + other.x, self.y + other.y )
   
    def __str__(self):
        return (self.x and self.y)
a = Point(3,5)
b = Point(1,2)
print(a+b)
```

    (4, 7)
    


```python
‘购物车类改造成方便操作的容器‘
class Cart:
    def __init__(self):
        self.items = []
    
    def __len(self):
        return len(self.items)
    
    def additem(self, item):
        self.items.append(item)
    
    def __iter__(self):
        return iter(self.items)
    
    def __getitem__(self, item):
        return self.items[item]
    
    def __setitem__(self, key, value):
        self.items[key] = value

cart = Cart()
cart.additem(1)
```

# 可调用对象:
    在python中,一切皆对象 函数也是
    __call__ 实例可以像函数一样被调用


```python
def foo(x):
    print(x)
foo(5)
print(foo.__dict__)
print(foo.__call__(5))
print(dir(foo))
```

    5
    {}
    5
    None
    [‘__annotations__‘, ‘__call__‘, ‘__class__‘, ‘__closure__‘, ‘__code__‘, ‘__defaults__‘, ‘__delattr__‘, ‘__dict__‘, ‘__dir__‘, ‘__doc__‘, ‘__eq__‘, ‘__format__‘, ‘__ge__‘, ‘__get__‘, ‘__getattribute__‘, ‘__globals__‘, ‘__gt__‘, ‘__hash__‘, ‘__init__‘, ‘__kwdefaults__‘, ‘__le__‘, ‘__lt__‘, ‘__module__‘, ‘__name__‘, ‘__ne__‘, ‘__new__‘, ‘__qualname__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__setattr__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘]
    


```python
class A:
    def __call__(self, *args, **kwargs):
        print(5

A()() # a = A() a()

```

    5
    


```python
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __call__(self, *args, **kwargs):
        return ""
```


```python
class Fib:
    
    def __init__(self):
        self.numlst = [0,1]
    def fib_iter(self, value):
        for i in range(value - 2):
            self.numlst.append(self.numlst[-2] + self.numlst[-1])
        return self.numlst
x = Fib()
x.fib_iter(10)
```


```python
class Fib:
    """
        f(n-1) + f(n-2)
    """
    def __init__(self):
        self.lst = [0,1]
    def fib_iter(self, values):
        ret = 0
        for i in range(values - 2):
            self.lst.append(self.lst[-2] + self.lst[-1])
        return self.lst
f = Fib()
f.fib_iter(9)
```




    [0, 1, 1, 2, 3, 5, 8, 13, 21]




```python
class Fib:
    """
        f(n-1) + f(n-2)
    """
    def __init__(self):
        self.lst = [0,1,1]

    def __call__(self, value):
        if value < len(self.lst): # 返回对象的长度减少计算量
            return self.lst
        for i in range(len(self.lst),value):
            self.lst.append(self.lst[i-1] + self.lst[i-2])
        return self.lst
    
    def __getitem__(self,index):#取索引 a[x] = xx
        if index < 0:
            return None
        if index < len(self.lst):
            return self.lst[index]
        else:
            self(index)
    def __iter__(self):
        return iter(self.lst) #可以迭代
fib = Fib()
fib(20)
for i in fib:
    print(i)
```

    0
    1
    1
    2
    3
    5
    8
    13
    21
    34
    55
    89
    144
    233
    377
    610
    987
    1597
    2584
    4181
    

# 上下文管理:
    __enter__  进入与此对象(实例)相关的上下文。如果存在该方法,with语法会把该方法的值作为绑定到as子句中指定的变量上
    __exit__  退出与此对象相关的上下文
    实例化对象的时候,不会调用enter,进入with语句块调用enter方法,然后执行语句体,最后离开with语句块的时候。调用exit方法
    with可以开启一个上下文运行环境,在执行前做一些准备工作,执行后做一些收尾工作
    
    
    上下文应用场景:
        1、增强功能
            在代码执行的前后增加代码,以增强其功能,类似装饰器
        2、资源管理
            打开了资源需要关闭,例如文件对象,网络连接,数据库连接等
        3、权限验证
            在执行代码之前,做权限的验证,在__enter__中处理
            


```python
class Point:
    """
        __enter__ 进去做的事情
        __exit__  退出做的事情
    """
    def __init__(self):
        print(‘init‘)
    def __enter__(self):
        print(self.__class__)
        return self
        
    def __exit__(self, exc_type, exc_val, exc_tb):
        print(self.__class__.__name__)
        print(exc_type)#异常类型
        print(exc_val)#异常的值
        print(exc_tb)#异常的追踪信息
        return 0#返回一个等效的值  True压制  False抛出异常
p = Point()
with p as f:
    raise Exception(‘Error-zz‘)
    print(f == p)#enter如果没有返回值 就为False
    print(f is p)
print(‘outer‘)
```

    init
    <class ‘__main__.Point‘>
    Point
    <class ‘Exception‘>
    Error-zz
    <traceback object at 0x0000019117DA9C48>
    


    ---------------------------------------------------------------------------

    Exception                                 Traceback (most recent call last)

    <ipython-input-227-cf8294135f8a> in <module>()
         18 p = Point()
         19 with p as f:
    ---> 20     raise Exception(‘Error-zz‘)
         21     print(f == p)#enter如果没有返回值 就为False
         22     print(f is p)
    

    Exception: Error-zz



```python
import datetime
import time
def times(fn):
    def wrapper(*args, **kwargs):
        start = datetime.datetime.now()
        print(args, kwargs)
        ret = fn(*args,**kwargs)
        after = datetime.datetime.now() - start   
        return ret
    return wrapper
@times
def add(x, y):
    time.sleep(2)
    return x + y
print(add(2,y=4))
```

    (2,) {‘y‘: 4}
    6
    


```python
import time
import datetime
from functools import wraps

class TimeIt:
    def __init__(self, fn):
        self._fn = fn
    def __enter__(self):
        print(‘enter‘)
        self.start = datetime.datetime.now()
        return self
    
    def __call__(self, *args, **kwargs):
        print(‘call‘)
        start = datetime.datetime.now() 
        print(args, kwargs)
        ret = self._fn(*args, **kwargs)
        delta = datetime.datetime.now() - start
        print(‘took{} s‘.format(delta))
        return ret
       #return self.fn(*args, **kwargs)
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        delta = (datetime.datetime.now() - self.start).total_seconds()
        print(‘exit‘)
        print(delta)
        return 

# def times(fn):
#     @wraps(fn)
#     def wrapper(*args, **kwargs):
#         start = datetime.datetime.now()
#         print(args, kwargs)
#         ret = fn(*args,**kwargs)
#         after = datetime.datetime.now() - start   
#         return ret
#     return wrapper
# @times
@TimeIt# add = TimeIt(add)
def add(x, y):
    time.sleep(2)
    return x + y
add(3,4)

# with TimeIt(add) as foo:
#     print(foo(5,3))
```

    call
    (3, 4) {}
    took0:00:02.000684 s
    


    ---------------------------------------------------------------------------

    TypeError                                 Traceback (most recent call last)

    <ipython-input-299-034e034cf759> in <module>()
         42     return x + y
         43 add(3,4)
    ---> 44 add.__doc__()
         45 # with TimeIt(add) as foo:
         46 #     print(foo(5,3))
    

    TypeError: ‘NoneType‘ object is not callable


# Contextlib.contextmanager
    它是一个装饰器实现上下文管理,装饰一个函数,不用像类一样实现__enter__和__exit__方法。
    对下面的函数有要求,必须有yield,也就是这个函数必定返回一个生成器,且只有yield一个值。


```python
import contextlib
@contextlib.contextmanager

def foo():
    print(‘enter‘)# 相当于 __enter__()
    yield 5 #作为__enter__方法的返回值
    print(‘exit‘)#相当于__exit__()
with foo() as f:
    print(f)
‘f接收yield语句的返回值‘
```

    enter
    5
    exit
    




    ‘f接收yield语句的返回值‘




```python
import contextlib

@contextlib.contextmanager

def foo():
    print(‘enter‘)
    try:
        yield 5 
    finally:
        print(‘exit‘)
with foo() as f:
    raise Exception()
    print(f)
#执行yield,为生成器函数增加了上下文管理
```

    enter
    exit
    


    ---------------------------------------------------------------------------

    Exception                                 Traceback (most recent call last)

    <ipython-input-6-cddb091c6a6e> in <module>()
         10         print(‘exit‘)
         11 with foo() as f:
    ---> 12     raise Exception()
         13     print(f)
    

    Exception: 



```python
import contextlib
import datetime
import time

@contextlib.contextmanager
def add(x, y):
    start = datetime.datetime.now()
    try:
        yield x + y
    finally:
        delta = (datetime.datetime.now()- start).total_seconds()
        print(delta)

with add(4,5) as f:
    time.sleep(3)
    print(f)
‘如果业务逻辑简单可以使用函数加装饰器方式,如果业务复杂,用类的方式加__enter__和__exit__方法方便。‘
```

    9
    3.000015
    




    ‘如果业务逻辑简单可以使用函数加装饰器方式,如果业务复杂,用类的方式加__enter__和__exit__方法方便。‘

  

魔术方法1

标签:typeerror   特殊   instance   dict   app   运算   last   ota   它的   

原文地址:http://www.cnblogs.com/hkcs/p/7860712.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!