目录
classmethod
classmethod是什么?
classmethod是一个装饰器,可以用来装饰类内部的方法,使该方法绑定给类来使用。
用classmethod绑定方法的目的
类的绑定方法的特殊之处
classmethod使被装饰的方法只能由类来调用,而且该方法会将类当做第一个参数传给该方法。这种方法被称为类的绑定方法。
(对象的绑定方法的特殊之处)
由对象来调用,会将对象当做第一个参数传给该方法。
如何使用classmethod
和正常装饰器一样,在需要被装饰的函数上方@classmethod就可以了。
staticmethod
staticmethod是什么?
staticmethod是一个装饰器,可以装饰给 类内部 的方法,使该方法既不绑定给对象,也不绑定给类。
为什么要使用staticmethod?
在类内部使用@staticmethod 修饰的方法既不绑定给对象,也不绑定给类。因此这种方法被称为非绑定方法。
如何使用staticmethod
和正常装饰器一样,在需要被装饰的函数上方@staticmethod 就可以了。
isinstance
isinstance(参数1, 参数2):
python内置的函数,可以传入两个参数,用于判断参数1是否是参数2的一个实例。参数1一般为对象,参数2是类。
class Foo: pass class Goo(Foo): pass foo_obj = Foo() print(isinstance(foo_obj, Foo)) # True print(isinstance(foo_obj, Goo)) # False
issubclass
issubclass(参数1, 参数2):
python内置的函数,可以传入两个函数,用于判断参数1是否是参数2 的子类。参数1和参数2都是类。
class Foo: pass class Goo(Foo): pass print(issubclass(Goo, Foo)) # True
反射
什么是反射
反射就是通过字符串来操作类或者对象的属性
反射的使用
反射有四种函数:
- hasattr:通过字符串,判断该字符串是否是对象或类的属性。
- getattr:通过字符串,获取对象或类的属性。
- setattr:通过字符串,设置对象或类的属性。
- delattr:通过字符串,删除对象或类的属性。
class People: country = 'China' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex p = People('tank', 17, 'male') # hasatter普通方式 # print(p.__dict__) # print(People.__dict__) # hasatter print(hasattr(p, 'name')) # True print(hasattr(People, 'country')) # True # getattr普通方式 print(p.__dict__.get('name', 'nick')) # tank print(p.__dict__.get('level', 9)) # 9 # 有就取值,没有就添加值 # getattr print(getattr(p, 'name', 'nick')) # tank print(getattr(p, 'salary', 15000)) # 15000 # 有就取值,没有就添加值 # setattr普通方法 p.level = 10 print(p.level) # 10 # setattr print(p.__dict__.get('salary')) # None print(hasattr(p, 'salary')) # False setattr(p, 'salary', 20000) print(hasattr(p, 'salary')) # True print(p.salary) # 20000 # delattr 普通方法 setattr(p, 'salary', 20000) print(hasattr(p, 'salary')) # True del p.salary print(hasattr(p, 'salary')) # False # delattr setattr(p, 'salary', 20000) print(hasattr(p, 'salary')) # True delattr(p, 'salary') print(hasattr(p, 'salary')) # False
魔法方法
凡是在类内部定义,以“__开头__结尾”的方法都称之为魔法方法,又称“类的内置方法”。魔法方法会在某些条件成立时触发。
如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而这一切都是自动发生的。
魔法方法 | 含义 |
---|---|
基本的魔法方法 | |
__new__ | 在__init__执行前触发 |
__init__ | 构造器,当一个实例被创建的时候(调用类时)触发 |
__del__ | 对象被销毁前执行该方法,该方法会在最后执行。 |
__str__ | 定义当打印方法被调用时的行为 |
__getattr__ | 会在对象.属性时,“属性没有”的情况下才会触发。 |
__setattr__ | 会在 “对象.属性 = 属性值” 时触发。(设置属性时触发) |
__call__ | 允许一个类的实例像函数一样被调用:x(a, b) 调用 x.__call__(a, b) |
class Foo(object): # 在调用之前触发,即在__init__()执行前触发,用来生成一个空的对象 def __new__(cls, *args, **kwargs): print('你在生成一个空的对象') # print(cls) print(object.__new__(cls)) return object.__new__(cls) # 如果没有return一个空对象,就不会触发__init__() # 在调用类时触发 def __init__(self): print('你在调用类') # 在打印一个实例化对象时触发 def __str__(self): print('你在打印对象') # 必须要有一个返回值,且改返回值必须是字符串 # 随便打印出来什么,只是显示了而已,和对象其实没什么关系 # 只是用来说明__str__出发了而已 return '随便' # 在实例化对象即将被回收时触发。 def __del__(self): print('对象即将被回收,且清空对内存的占用') # 在试图获取一个不存在的属性时触发 def __getattr__(self, item): print('你在试图获取一个不存在的属性') print(item) # item即为那个不存在的属性的属性名 # 其实,你在用print方法来打印(对象.属性)时, # 虽然这个属性不存在,但是也是可以打印出结果的, # 印出的内容即是__getattr__()函数返回的值, # 没有返回内容,默认返回None。 return f'{self}.{item} 属性不存在' # 你在打印对象 # 随便.x 属性不存在 # return f'{item} 属性不存在' # 在进行设置属性(赋值)操作时触发 def __setattr__(self, key, value): # key为属性的属性名,value为设置属性的属性值 print('你在设置一个对象的属性') print(self.__dict__) print('key =',key,'value =',value) self.__dict__['key'] = value print('设置成功!') print(self.__dict__) # 在调用 对象 时触发 def __call__(self, *args, **kwargs): print('你在调用一个对象!') # 即将调用类,触发__new__() # 你在生成一个空的对象 # <class '__main__.Foo'> # 你在打印对象 # 随便 # 对象即将被回收,且清空对内存的占用 # 此时在调用类,触发__init__() foo = Foo() # 你在调用类 # 此时在打印类,啥也没发生,就正常打印类 print(Foo) # <class '__main__.Foo'> # 此时在打印对象,触发__str__() print(Foo()) # 在打印对象时触发 # 随便 print(foo) # 在打印对象时触发 # 随便 # 如果没有__str__ 就是一个地址: # <__main__.Foo object at 0x0000022BA3C38188> # 此时在试图获取一个不存在的属性,触发__getattr__() foo.x # 你在试图获取一个不存在的属性 # x print(foo.x) # 你在试图获取一个不存在的属性 # x # x 属性不存在 # 这里在调用一个对象,触发__call__() foo() # 你在调用一个对象! # 这里在进行设置属性(赋值)操作,触发__setattr__() foo.x = 10 # 你在设置一个对象的属性 # key = x value = 10 # 此时实例化对象被回收时,触发__del__() del foo print('文件这个时候才运行结束') # 对象即将被回收,且清空对内存的占用 # 文件这个时候才运行结束 ''' 你在生成一个空的对象 你在打印对象 随便 对象即将被回收,且清空对内存的占用 你在调用类 <class '__main__.Foo'> 你在生成一个空的对象 你在打印对象 随便 对象即将被回收,且清空对内存的占用 你在调用类 你在打印对象 随便 对象即将被回收,且清空对内存的占用 你在打印对象 随便 你在试图获取一个不存在的属性 x 你在打印对象 你在试图获取一个不存在的属性 x 你在打印对象 随便.x 属性不存在 你在调用一个对象! 你在设置一个对象的属性 {} key = x value = 10 设置成功! {'key': 10} 对象即将被回收,且清空对内存的占用 文件这个时候才运行结束 '''
单例模式
单例模式指的是单个实例,实例指的时调用类产生的对象.
实例化多个对象会产生不同的内存地址,单例可以让所有调用者,在调用类产生对象的情况下都指向同一份内存地址。
例如: 打开文件。
单例的目的: 为了减少内存的占用。
class File: __instance = None # 单例方式1: @classmethod def singleton(cls, file_name): if not cls.__instance: obj = cls(file_name) cls.__instance = obj return cls.__instance # 单例方式2: def __new__(cls, *args, **kwargs): # cls.__new__(cls, *args, **kwargs) if not cls.__instance: cls.__instance = object.__new__(cls) return cls.__instance def __init__(self, file_name, mode='r', encoding='utf-8'): self.file_name = file_name self.mode = mode self.encoding = encoding def open(self): self.f = open(self.file_name, self.mode, encoding=self.encoding) def read(self): res = self.f.read() print(res) def close(self): self.f.close() # 方式1: # obj1 = File.singleton('jason雨后的小故事.txt') # singleton(cls) # obj2 = File.singleton('jason雨后的小故事.txt') # singleton(cls) # obj3 = File.singleton('jason雨后的小故事.txt') # singleton(cls) # obj1 = File('jason雨后的小故事.txt') # obj2 = File('jason雨后的小故事.txt') # obj3 = File('jason雨后的小故事.txt') # print(obj1) # print(obj2) # print(obj3) # 方式2: obj1 = File('jason雨后的小故事.txt') # singleton(cls) obj2 = File('jason雨后的小故事.txt') # singleton(cls) obj3 = File('jason雨后的小故事.txt') # singleton(cls) print(obj1) print(obj2) print(obj3)