Magic and the objects of the method for a single module Examples

Magic Methods

Those who defined within the class, with method "__ __ beginning of the end" are called magic method, also known as "built-in method of class", these methods will be triggered when certain conditions are met.

Double Down method often used

__init__: 在调用类时触发。
__delarttr__:
__getattr__: 会在对象.属性时,“属性没有”的情况下才会触发。对象.__dict__[属性]不会触发__getattr__,会报keyerror;
__getattribute__:会在对象.属性时触发,不管有没有该属性都会触发;
__setattr__: 会在 “对象.属性 = 属性值” 时触发。即:设置(添加/修改)属性会触发它的执行;
__del__: 当对象在内存中被释放时,自动触发执行,该方法会在最后执行。

class Uderline_func:

    x = 100
    
    def __init__(self, y):
        print('类加括号调用的时候触发我!')
        self.y = y  # 当与__setattr__方法同时存在时,self.y = y并不会被加载到对象的名称空间
        # self['y'] = y  # TypeError: 'Uderline_func' object does not support item assignment
    def general_func(self):
    
        print('随便定义的一个函数!')


    # def __getattr__(self, item):
    #     print('只有对象获取一个没有的属性值得时候触发我!')
    
    def __getattribute__(self, item):
    
        print('类或对象无论获取的属性有没有都会触发我!且出现我,对象点一个没有的属性会覆盖掉__getattr__,还会导致__setattr__函数报错')
    
    def __setattr__(self, key, value):
    
        print('设置属性的时候触发我!')
        # self.a = '在对象名称空间增加一个值!'  # 会一直触发__setattr__,出现递归调用
        self.__dict__['a'] = '在对象名称空间增加一个值!'
    def __delattr__(self, item):
    
        print('删除值得时候触发我!')
    
    def __del__(self):
    
        print('程序运行完,被Python解释器回收时,触发我!')

# print(Uderline_func.__dict__)  # 类在定义阶段就已经创建好了类名称空间,将其内部变量名和函数名塞进去

u = Uderline_func(100)  # 触发__init__
# print(u.__dict__)  # {'y': 100}

# Uderline_func.z  # 只会触发__getattribute__
u.z  # 获取没有的属性触发__getattr__

# u.name = 'zhang'  # 触发__setattr__

# del u.x  # 对象不能删除掉类中的属性,但只要执行删除操作,都会触发__delattr__的执行
__str__: 会在打印对象时触发。
__call__: 会在对象被调用时触发。
__new__: 会在__init__执行前触发。
class Uderline_func():

    x = 100
    # def __new__(cls, *args, **kwargs):
    #
    #     print('在__init__执行之前触发我,造一个空对象!')

    def __init__(self):
        print('类加括号调用的时候触发我!')

    def __call__(self, *args, **kwargs):

        print('对象加括号调用的时候触发我!')

    def __str__(self):

        print('对象被打印的时候触发我!')

        return '必须要写return返回一个字符串!不然报错"TypeError: __str__ returned non-string (type NoneType)"'


u = Uderline_func()
u()

print(u)
 __setitem__,__getitem,__delitem__

class Foo:
    def __init__(self,name):
        self.name=name

    def __getitem__(self, item):
        print(self.__dict__[item])

    def __setitem__(self, key, value):
        self.__dict__[key]=value

        # self.age = value  # 也可以给对象添加属性


    def __delitem__(self, key):
        print('del obj[key]时,我执行')
        self.__dict__.pop(key)
    def __delattr__(self, item):
        print('del obj.key时,我执行')
        self.__dict__.pop(item)

f1=Foo('sb')
f1['age']=18
# print(f1.__dict__)
f1['age1']=19
# del f1.age1
# del f1['age']
f1['name']='alex'
f1.xxx = 111
print(f1.__dict__)  # {'name': 'alex', 'age': 18, 'age1': 19, 'xxx': 111}
1.__slots__是什么:是一个类变量,变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性)
2.引子:使用点来访问属性本质就是在访问类或者对象的__dict__属性字典(类的字典是共享的,而每个实例的是独立的)
3.为何使用__slots__:字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用__slots__取代实例的__dict__
当你定义__slots__后,__slots__就会为实例使用一种更加紧凑的内部表示。实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个
字典,这跟元组或列表很类似。在__slots__中列出的属性名在内部被映射到这个数组的指定小标上。使用__slots__一个不好的地方就是我们不能再给
实例添加新的属性了,只能使用在__slots__中定义的那些属性名。
4.注意事项:__slots__的很多特性都依赖于普通的基于字典的实现。另外,定义了__slots__后的类不再 支持一些普通类特性了,比如多继承。大多数情况下,你应该
只在那些经常被使用到 的用作数据结构的类上定义__slots__比如在程序中需要创建某个类的几百万个实例对象 。
关于__slots__的一个常见误区是它可以作为一个封装工具来防止用户给实例增加新的属性。尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。           更多的是用来作为一个内存优化工具。
class Foo:
    __slots__ = 'x'


f1 = Foo()
f1.x = 1
f1.y = 2  # 报错
print(f1.__slots__)  # f1不再有__dict__属性
print(f1.x)  #依然能访问


class Bar:
    __slots__ = ['x', 'y']


n = Bar()
n.x, n.y = 1, 2
n.z = 3  # 报错
__doc__:查看类中注释
class Foo:
    '我是描述信息'
    pass
print(Foo.__doc__)
class Foo:
    '我是描述信息'
    pass

class Bar(Foo):
    pass
print(Bar.__doc__) #该属性无法继承给子类
 __module__和__class__
 
 __module__:表示当前操作的对象在那个模块
 __class__:表示当前操作的对象的类是什么
class C:

    def __init__(self):
        self.name = ‘SB'
from lib.aa import C

obj = C()
print obj.__module__  # 输出 lib.aa,即:输出模块
print obj.__class__      # 输出 lib.aa.C,即:输出类
__enter__和__exit__

We know could write operation when the file object

 with open('a.txt') as f:
   '代码块'

Above is called context management protocol, namely with the statement, in order to allow an object compatible with the statement, must be declared in the class __enter__ and methods of this object in __exit__

class Open:
    def __init__(self,name):
        self.name=name

    def __enter__(self):
        print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
        # return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('with中代码块执行完毕时执行我啊')

with Open('a.txt') as f:
    print('=====>执行代码块')
    # print(f,f.name)
    
'''
出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
=====>执行代码块
with中代码块执行完毕时执行我啊
'''

exit three parameters () represent the exception type, and outlier traceability information, with exception code block appears the statement, the code can not be performed with the

class Open:
    def __init__(self,name):
        self.name=name

    def __enter__(self):
        print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('with中代码块执行完毕时执行我啊')
        print(exc_type)
        print(exc_val)
        print(exc_tb)


with Open('a.txt') as f:
    print('=====>执行代码块')
    raise AttributeError('***着火啦,救火啊***')
print('0'*100) #------------------------------->不会执行


'''
出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
=====>执行代码块
with中代码块执行完毕时执行我啊
<class 'AttributeError'>
***着火啦,救火啊***
<traceback object at 0x000000000A001E88>
Traceback (most recent call last):
  File "G:/Python代码日常/第一阶段/1阶段/面向对象/test.py", line 52, in <module>
    raise AttributeError('***着火啦,救火啊***')
AttributeError: ***着火啦,救火啊***

'''

If __exit () return value is True, then the exception will be emptied, as if got nothing happened, after the sentence with normal execution

class Open:
    def __init__(self,name):
        self.name=name

    def __enter__(self):
        print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('with中代码块执行完毕时执行我啊')
        print(exc_type)
        print(exc_val)
        print(exc_tb)
        return True
   with Open('a.txt') as f:
    print('=====>执行代码块')
    raise AttributeError('***着火啦,救火啊***')
print('0'*100) #------------------------------->会执行
class Open:
    def __init__(self,filepath,mode='r',encoding='utf-8'):
        self.filepath=filepath
        self.mode=mode
        self.encoding=encoding

    def __enter__(self):
        # print('enter')
        self.f=open(self.filepath,mode=self.mode,encoding=self.encoding)
        return self.f

    def __exit__(self, exc_type, exc_val, exc_tb):
        # print('exit')
        self.f.close()
        return True 
    def __getattr__(self, item):
        return getattr(self.f,item)

with Open('a.txt','w') as f:
    print(f)
    f.write('aaaaaa')
    f.wasdf #抛出异常,交给__exit__处理

Uses or benefits:

1. Use with the statement of purpose is to put the code block with the execution after the end with, clean up automatically, without manual intervention

2. On the need to manage some resources such as files, network connections, and lock the programming environment, you can customize the mechanism automatically release resources __exit__, you do not need to go to the relationship between this problem, which will be of great use

Singleton

Singleton pattern: multiple instances of the same instance results point

Mode 1

# @classmethod(用类绑定方法)

import settings

class MySQL:
    __instance=None
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

    @classmethod
    def from_conf(cls):
        if cls.__instance is None:
            cls.__instance=cls(settings.IP, settings.PORT)
        return cls.__instance
obj1=MySQL.from_conf()
obj2=MySQL.from_conf()
obj3=MySQL.from_conf()
# obj4=MySQL('1.1.1.3',3302)
print(obj1)
print(obj2)
print(obj3)
# print(obj4)

Mode 2

# 用类装饰器
import settings

def singleton(cls):
  _instance=cls(settings.IP,settings.PORT)
  def wrapper(*args,**kwargs):
      if len(args) !=0 or len(kwargs) !=0:
          obj=cls(*args,**kwargs)
          return obj
      return _instance
  return wrapper

@singleton #MySQL=singleton(MySQL) #MySQL=wrapper
class MySQL:
  def __init__(self, ip, port):
      self.ip = ip
      self.port = port

# obj=MySQL('1.1.1.1',3306) #obj=wrapper('1.1.1.1',3306)
# print(obj.__dict__)

obj1=MySQL() #wrapper()
obj2=MySQL() #wrapper()
obj3=MySQL() #wrapper()
obj4=MySQL('1.1.1.3',3302) #wrapper('1.1.1.3',3302)
print(obj1)
print(obj2)
print(obj3)
print(obj4)

Mode 3

# 调用元类
import settings

class Mymeta(type):
    def __init__(self,class_name,class_bases,class_dic):
        #self=MySQL这个类
        self.__instance=self(settings.IP,settings.PORT)

    def __call__(self, *args, **kwargs):
        # self=MySQL这个类
        if len(args) != 0 or len(kwargs) != 0:
            obj=self.__new__(self)
            self.__init__(obj,*args, **kwargs)
            return obj
        else:
            return self.__instance

class MySQL(metaclass=Mymeta): #MySQL=Mymeta(...)
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port


obj1=MySQL()
obj2=MySQL()
obj3=MySQL()
obj4=MySQL('1.1.1.3',3302)
print(obj1)
print(obj2)
print(obj3)
print(obj4)

Mode 4

# 利用模块多次导入只产生一次名称空间,多次导入只沿用第一次导入成果。
def f1():
    from singleton import instance
    print(instance)

def f2():
    from singleton import instance,My
    SQL
    print(instance)
    obj=MySQL('1.1.1.3',3302)
    print(obj)

f1()
f2()

Guess you like

Origin www.cnblogs.com/zhangchaocoming/p/11706501.html