Day 22 绑定方法和非绑定方法/isinstance/issubclass/反射/魔法方法/单例模式
类和对象的绑定方法与非绑定方法
类中定义的方法大致可以分成两类:绑定方法和非绑定方法.其中绑定方法又可以分为对象的绑定方法和类的绑定方法
绑定方法
对象的绑定方法
在类中没有被任何装饰器修饰的方法就是对象的绑定方法
对象的绑定方法的特殊之处在于调用方法时会自动将当前对象传给方法的第一个参数
类的绑定方法
类中使用 @classmethod 装饰器修饰的方法就是绑定到类的方法
类的绑定方法的特殊之处在于利用类名调用方法时,会自动将当前类传给方法的第一个参数
class Foo:
@classmethod
def foo(cls):
print('这是类的绑定方法')
Foo.foo()
print(Foo.foo)
这是类的绑定方法
<bound method Foo.foo of <class '__main__.Foo'>>
通过对象也可以调用,只不过默认传递的第一个参数还是这个对象对应的类
非绑定方法
类中使用 @staticmethod 装饰器修饰的方法就是非绑定方法
这类方法和普通定义的函数没有区别,不与类或对象绑定,谁都可以调用,并且没有自动传入的值
import uuid
class Student:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
self.stu_id = self.creat_id()
@staticmethod
def creat_id():
stu_id = uuid.uuid1()
return stu_id
stu1 = Student('Tiny', 18, 'male')
print(stu1.creat_id())
print(stu1.stu_id)
print(Student.creat_id())
b082496d-ecc0-11e9-afa2-005056c00008
b082496c-ecc0-11e9-9089-005056c00008
b082496e-ecc0-11e9-ab2d-005056c00008
小结
如果函数体代码需要用外部传入的类,那么就要把函数定义成绑定类的方法
如果函数体代码需要用外部传入的对象,那么就要把函数定义成绑定对象的方法
如果函数体代码既不需要从外部传入类,也不需要从外部传入对象,则应该将该函数定义成非绑定方法
isinstance
可以传入两个参数,用于判断参数一是否是参数二的一个实例
class Foo:
pass
class Soo(Foo):
pass
print(isinstance(Soo(), Foo))
True
issubclass
可以传入两个参数,用于判断参数1是否是参数二的子类
class Foo:
pass
class Soo(Foo):
pass
print(issubclass(Soo, Foo))
True
反射
反射就是通过字符串来操作类或者对象的属性
- hasattr: 通过字符串,判断该字符串是否是类或者对象的属性
- getattr: 通过字符串,获取类或者对象的属性
- setattr: 通过字符串,设置类或者对象的属性
- delattr: 通过字符串,删除类或者对象的属性
class People:
def __init__(self, name, age):
self.name = name
self.age = age
# hasattr
p = People('Tiny', 18)
print(hasattr(p, 'name'))
# getattr
print(getattr(p, 'gender', 'male'))
print(p.__dict__)
print(hasattr(p, 'gender'))
# setattr
setattr(p, 'gender', 'male')
print(p.__dict__)
print(hasattr(p, 'gender'))
# delattr
delattr(p, 'gender')
print(p.__dict__)
print(hasattr(p, 'gender'))
魔法方法
凡是类内部定义,以__开头__结尾的方法都称之为魔法方法,又称为类的内置方法
魔法方法会在某些条件成立时触发
'''
__init__: 在调用类的时候触发
__str__: 在打印对象时触发
__del__: 对象被销毁前执行该方法
__getattr__: 会在 对象.属性 时,属性没有的情况下触发
__setattr__: 会在 对象.属性 = 属性值 时触发
__call__: 会在对象被调用的时候触发
__new__: 会在__init__执行前触发
'''
class MagicalMethod:
def __init__(self):
print('调用类的时候触发我')
def __str__(self):
print('打印对象的时候触发我')
return '必须要有返回值哦'
def __del__(self):
print('对象销毁前触发我')
print(self)
def __getattr__(self, item):
print(item)
return '没返回值默认返回None'
def __setattr__(self, key, value):
print(key, value)
def __call__(self, *args, **kwargs):
print('对象被调用时触发我')
# def __new__(cls):
# print('在执行__init__前调用我')
m = MagicalMethod()
print(m.x)
m.x = 1
m()
单例模式
class Student:
__instance = None
# @classmethod
# def singleton(cls, name, age):
# if not cls.__instance:
# cls.__instance = cls(name, age)
# return cls.__instance
def __new__(cls, *args, **kwargs):
if not cls.__instance:
cls.__instance = super().__new__(cls)
return cls.__instance
def __init__(self, name, age):
self.name = name
self.age = age
stu1 = Student('Tiny', 18)
stu2 = Student('nick', 18)
print(stu1)
print(stu2)
print(stu1.name)
print(stu2.name)
# stu1 = Student.singleton('Tiny', 18)
# stu2 = Student.singleton('Nick', 18)
# print(stu1)
# # print(stu2)
# print(stu1.name)
# # print(stu2.name)
<__main__.Student object at 0x004563B0>
<__main__.Student object at 0x004563B0>
nick
nick