• 1012 笔记


    类的方法

    classmethod

    一个类的绑定方法 classmethod是一个装饰器,可以装饰给类内部的方法,使该方法绑定给类使用

    一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法。而使用@classmethod,就可以不需要实例化,直接类名.方法名()来调用。

    不需要self参数,但第一个参数需要是表示自身类的cls参数。
    
    对象的绑定方法特殊之处:
    	由对象调用,会将对象当做第一个参数传给该方法
    类的绑定方法特殊之处:
    	由类调用,会将类当做第一个参数传给该方法
    
    class A(object):
        bar = 1
    
        def foo(self):
            print ('foo')
    
        @classmethod
        def class_foo(cls):  # cls是调用的类的本身
            print('class_foo')
            '''可以在方法中 cls.属性 cls是调用的类本身'''
            print(cls.bar)
            # cls() 调用类 .方法  使用
            cls().foo()
            
    ###执行可以直接类名.方法没有实例化对象
    A.class_foo()
    '''
    class_foo
    1
    foo
    '''
    

    课堂代码

    import setting
    class teacher:
    
        def __init__(self,user,password):
            self.user = user
            self.pwd = password
    
        def index(self):
            # 判断传进来的类的user pwd是都相等
            if self.user == 'aaa' and self.pwd == '123':
                print('验证通过...')
    
        @classmethod
        def login_tell(cls):
            '''将setting文件中的用户密码传入cls的类函数中,并得到返回值
            cls() == teacher()'''
            res = cls(setting.user,setting.pwd)
            return res
            '''返回得到的'''
    
    '''res接受'''
    res = teacher.login_tell()
    '''使用res 调用index方法'''
    res.index()
    

    staticmethod

    类的非绑定方法是一个装饰器,可以装饰给类内部的方法,使该方法既不绑定给对象,也不绑定给类.

    @staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。
    
    在@staticmethod中要调用到这个类的一些属性方法,只能直接类名.属性名或类名.方法名方式。
    

    UUID模块

    可以通过.uuid4 获取一个唯一的时间戳字符串

    用法

    @staticmethod
    class teacher:
        def creat_id():
            # 生成特定的字符串id
            uuid_s = uuid.uuid4()
            md5 = hashlib.md5()
            md5.update(str(uuid_s).encode('utf-8'))
            return md5.hexdigest()
    
    print(teacher.creat_id())
    # 由类调用不需要传值
    t = teacher('ntank','123')
    print(t.creat_id())
    # 由对象调用也不需要传值
    

    面向对象高阶

    isinstance(参数1,参数2)

    python内置的函数,可以传入两个参数,用来判断参数1是否是参数2的一个实例

    判断一个对象是否是一个类的实例

    class Foo:
        pass
    
    class Goo(Foo):
        pass
    
    obj = Foo()
    print(isinstance(Goo(),Foo))
    print(isinstance(obj,Foo))
    

    issubclass

    python内置函数,可以传入两个参数,用来判断参数1是否是参数2的子类

    判断一个类是否是另一个类的子类

    class Foo:
        pass
    
    class Goo(Foo):
        pass
    
    class aa:
        pass
    print(issubclass(Goo,Foo)) # True
    print(isinstance(Foo,Goo)) # False
    print(isinstance(aa,Goo))  # False
    

    反射

    通过字符串对象或类的属性进行操作

    '''反射本质就是在使用内置函数,其中反射有以下四个内置函数:'''
    通过字符串
    -hasattr:	判断该字符串是否是对象或类的属性
    -getattr:	获取对象或类的属性
    -setattr:	设置对象或类的属性
    -delattr:	删除对象或类的属性
    
    
    class People:
        country = 'China'
    
        def __init__(self,name,age):
            self.name = name
            self.age = name
    
    

    hasattr

    # hasattr  判断是否在
    p = People('tank',18)
    print (hasattr(p,'name'))	# True
    print (hasattr(p,'uzi'))	# False
    
    

    getattr

    # getattr
    print(getattr(p,'name'))	# tank
    print(getattr(p,'uzi'))  # 'People' object has no attribute 'uzi'
    
    

    setattr

    # setattr
    setattr(p,'level','SSS')
    print(getattr(p,'level'))    # SSS
    
    
    

    delattr

    # delattr
    delattr(p,'level')
    print (hasattr(p,'level'))  #  False
    
    

    反射方法的练习,用户输入字符串反射至类中方法

    class D:
        def inpu(self):
            print('请输入')
            while True:
                inp = input('请输入模块名').strip()
                if hasattr(self,inp):
                    func = getattr(self,inp)
                    func()
                    break
                else:
                    print('命令错误,请重新输入')
        def p(self):
            print('即将打印pppp')
        def s(self):
            print('即将打印sss')
    
    d = D()
    d.inpu()
    
    

    魔法方法

    凡是在类内部定义,以__开头,以__结尾的方法都称之为魔法方法,又称'类的内置方法'

    魔法方法会在某些条件成立时触发

    '''__init__	: 在调用类时触发
       __str__	: 会在打印对象时触发
       __del__	:对象被销毁前执行该方法,且总是在最后被执行
       __getattr__:会在对象.属性,''属性''没有的情况下才会触发
       __setattr__:会在 ''对象.属性 = 属性值'' 时触发
       __call__
       __new__
       
       '''
    class Foo:
        def __init__(self):
            print('在调用类时触发')
        def __str__(self):
            print('会在打印对象时触发')
            # 必须有一个返回值,该返回值必须是字符串类型
            return '返回的值'
        
        def __del__(self):
            print('对象被销毁前执行该方法,且总是在最后被执行')
            
        def
        
        def __setattr__(self,key,val):
            print('会在 ''对象.属性 = 属性值'' 时触发')
        
        
        
        
        
    f = Foo()
    
    
    
    
    
    
    
    
    
    

    1.__init__

    对象实例化的时候自动触发
    
    

    2.__str__

    class Foo:
        def __init__(self,name,age):
            '''实例化时自动触发'''
            self.name = name
            self.age = age
    
        def __str__(self):
            # print('打印时自动触发,不需要print即可打印')
            return f'{self.name}:{self.age}'# return出的就是最后打印的值.可以随意返回
            # 如果不返回字符串类型,则会报错
    obj = Foo('nick',18)
    print(obj)   # obj.__str__() # 打印的时候就是在打印返回值
    
    

    3.__del__

    '''__del__,对象被销毁时执行,且总会在最后被执行'''
    class AA:
        def __del__(self):
            print('对象被销毁前执行该方法,且总是在最后被执行')
    
    

    4.__getattr__

    默认返回none,可以return任何值

    '''__getattr__ 会在对象.属性时,'属性没有'的情况下才会触发'''
    
    class aaa:
        def __getattr__(self,item):
            print('对象.属性,属性没有的时候触发')
            print(item)  # item就是没有的属性
       
    a = aaa()
    a.x   # 类中没有x属性,但会在__getattr__被触发打印
    '''
    对象.属性,属性没有的时候触发
    x
    '''
    
    

    5.__setattr__

    添加/修改属性会触发他的执行

    '''会在'对象.属性 = 属性值'时来触发'''
    
    class aaa:
        def __setattr__(self, key, value):
            print('会在对象.属性 = 属性值时触发,赋值时')
            print(key, value)  # 就是赋值的属性值
    a = aaa()
    a.i=10
    # 会在对象.属性 = 属性值时触发,赋值时
    # i 10
    
    

    6.__call__

    会在调用对象时触发
    class aaa:
        def __call__(self, *args, **kwargs):
            print(self) # <__main__.aaa object at 0x0000016E0D605940>
            print('在调用对象时触发该方法...') # 在调用对象时触发该方法...
            
    a = aaa()
    a()  # 对象加()调用
    
    

    7.__new__

    #__new__是在实例创建之前被调用的,因为它的任务就是创建实例然后返回该实例,是个静态方法。
    #__new__在__init__之前被调用,__new__的返回值(实例)将传递给__init__方法的第一个参数,然后__init__给这个实例设置一些参数
    
    相当于要做三件事,
    
    1.调用`__new__`创建对象,然后找一个变量来接受`__new__`的返回值,这个返回值表示创建出来的对象的引用
    
    2.`__init__`(刚刚创建出来的对象的应用)
    
    3.返回对象的引用
    
    

    总结:

    __new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供
    
    __new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例
    
    __init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值
    
    我们可以将类比作制造商,__new__方法就是前期的原材料购买环节,__init__方法就是在有原材料的基础上,加工,初始化商品环节
    
    

    魔法方法的应用

    __del__

    class MyFile:
        def __init__(self,file_name,mode = 'r',encoding = 'utf-8'):
            self.file_name = file_name
            self.mode = mode
            self.encoding = encoding
    
        def file_open(self):
            self.f = open(self.file_name,self.mode,encoding= self.encoding)
    
        def read_file(self):
            res = self.f.read()
            print(f'''
            当前文本名是
    {self.file_name}
            文本内容为
    {res}
            ''')
    
        def __del__(self):
            self.f.close()
            print('文件关闭成功')
    
    f = MyFile('1.txt')
    f.file_open()
    f.read_file()
    print('文件销毁')
    
    

    单例模式

    1.定义

    单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

    实例化多个对象,会产生不同的内存地址,单例可以让所有调用者,在调用类产生对象的情况下都执行同一份内存地址.例如打开文件的操作

    比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。
    
    

    2.单例的目的:

    减少内存的占用

    3.实现单例模式

     意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
     主要解决:一个全局使用的类频繁地创建与销毁。
     何时使用:当您想控制实例数目,节省系统资源的时候。
     如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。
     关键代码:构造函数是私有的。
    
    
    • 使用模块
    • 使用__new__
    • 使用装饰器
    • 使用元类

    1.使用模块

    python模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。

    # mysingleton.py
    class My_Singleton(object):
        def foo(self):
            pass
    
    my_singleton = My_Singleton()
    
    

    将上面的代码保存在文件 mysingleton.py 中,然后这样使用:

    from mysingleton import my_singleton
    
    my_singleton.foo()
    
    

    2.使用__new__

    知识点:
    1> 一个对象的实例化过程是先执行类的`__new__方法`,如果我们没有写,默认会调用object的`__new__`方法,返回一个实例化对象,然后再调用`__init__方法`,对这个对象进行初始化,我们可以根据这个实现单例.
    
    2> 在一个类的`__new__方法中`先判断是不是存在实例,如果存在实例,就直接返回,如果不存在实例就创建.
    
    重写 __new__ 方法 一定要 return super().__new__(cls)*   否则 Python 的解释器 得不到 分配了空间的 对象引用,就不会调用对象的初始化方法
    注意:__new__ 是一个静态方法,在调用时需要 主动传递 cls 参数
    
    

    为了使类只能出现一个实例,我们可以使用__new__来控制实例的创建

    我们将类的实例和一个类变量 _instance 关联起来,如果 cls._instance 为 None 则创建实例,否则直接返回 cls._instance

    class Singleton(object):
        _instance = None
        def __new__(cls, *args, **kw):
            if not cls._instance:
                cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)  
            return cls._instance  
    
    class MyClass(Singleton):  
        a = 1
    
    

    3.使用装饰器

    装饰器可以动态的修改一个类或函数的功能, 在此,使用装饰器来装饰某个类,使其只能生成一个实例

    装饰器里面的外层变量定义一个字典,里面存放这个类的实例.当第一次创建的时候,就将这个实例保存到这个字典中.
    然后以后每次创建对象的时候,都去这个字典中判断一下,如果已经被实例化,就直接取这个实例对象.如果不存在就保存到字典中.

    __author__ = 'Fioman'
    __time__ = '2019/3/6 10:22'
    
    
    def singleton(cls):
        # 单下划线的作用是这个变量只能在当前模块里访问,仅仅是一种提示作用
        # 创建一个字典用来保存类的实例对象
        _instance = {}
    
        def _singleton(*args, **kwargs):
            # 先判断这个类有没有对象
            if cls not in _instance:
                _instance[cls] = cls(*args, **kwargs)  # 创建一个对象,并保存到字典当中
            # 将实例对象返回
            return _instance[cls]
    
        return _singleton
    
    
    @singleton
    class A(object):
        a = 1
    
        def __init__(self, x=0):
            self.x = x
            print('这是A的类的初始化方法')
    
    
    a1 = A(2)
    a2 = A(3)
    print(id(a1), id(a2))
    
    

    换个思路

    from functools import wraps
    
    def singleton(cls):
        instances = {}
        @wraps(cls)
        def getinstance(*args, **kw):
            if cls not in instances:
                instances[cls] = cls(*args, **kw)
            return instances[cls]
        return getinstance
    
    @singleton
    class MyClass(object):
        a = 1
    
    

    在上面,我们定义了一个装饰器 singleton,它返回了一个内部函数 getinstance,该函数会判断某个类是否在字典 instances 中,如果不存在,则会将 cls 作为 key,cls(*args, **kw) 作为 value 存到 instances 中,否则,直接返回 instances[cls]

    4.使用metaclass

    元类可以控制类的创建过程,他主要做三件事:

    • 拦截类的创建
    • 修改类的定义
    • 返回修改后的类

    使用元类实现单例模式的代码如下

    class Singleton(type):
        _instances = {}
        def __call__(cls, *args, **kwargs):
            if cls not in cls._instances:
                cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
            return cls._instances[cls]
    
    class MyClass(metaclass=Singleton):
       pass
    
    

    总结

    Python 的模块是天然的单例模式,这在大部分情况下应该是够用的,当然,我们也可以使用装饰器、元类等方法

  • 相关阅读:
    SQL SERVER 修改表名、列名
    AgilePLM维护中,重启能解决的问题
    联通银铃小龙卡3G流量领取方法
    更改github默认分支main为master
    SQL基础:显示不存在的分组数量为0
    关于添加EF CODE First的问题
    安装Windows Service总是发生异常!
    通过Anaconda3pip安装opencvpython包失败的处理方法(亲测有效)
    jenkins安装及配置(一)
    Windows添加多个github ssh秘钥域名映射
  • 原文地址:https://www.cnblogs.com/fwzzz/p/11668335.html
Copyright © 2020-2023  润新知