# 利用面向对象编写系统终端功能 class WinCmd(object): def ls(self): print('windows系统正在执行ls命令') def dir(self): print('windows系统正在执行dir命令') def cd(self): print('windows系统正在执行cd命令') class LinuxCmd(object): def ls(self): print('linux系统正在执行ls命令') def dir(self): print('linux系统正在执行dir命令') def cd(self): print('linux系统正在执行cd命令') obj1 = WinCmd() obj2 = LinuxCmd() def run(obj): while True: cmd = input('输入命令>>>:').strip() # hasattr():判断对象是否含有字符串对应的数据或者功能 # 即判断obj内有无输入的cmd对应的变量名或函数名 if hasattr(obj, cmd): # getattr():根据字符串获取对应的变量名或者函数名 # 有的话取出obj内对应的cmdd的变量名或函数名 func = getattr(obj, cmd) func() else: print('命令不存在') run(obj1) run(obj2)
1. __str__ # 对象被执行打印(print、前端展示)操作的时候自动触发 # 该方法必须返回字符串类型的数据 # 很多时候用来更加精准的描述对象
class Myclass(object): def __init__(self, name, age): self.name = name self.age = age obj1 = Myclass('cc', 22) print(obj1) # 我们直接打印对象的时候显示的是其内存地址 # <__main__.Myclass object at 0x00000203DED76430>
使用__str__方法后:必须return一个字符串,这个返回的字符串就是我们打印的内容
class Myclass(object): def __init__(self, name, age): self.name = name self.age = age def __str__(self): return '打印的变成我了' obj1 = Myclass('cc', 22) print(obj1) # 打印的变成我了
2. __del__ # 对象被执行(被动、主动)删除操作之后自动执行
class Myclass(object): def __init__(self, name, age): self.name = name self.age = age def __del__(self): """对象被执行(被动、主动)删除操作之后自动执行""" print('我执行了')
主动删除:使用del关键字主动删除
obj2 = Myclass('cc', 22) del obj2 # 主动删除对象 print(obj2.name)
输出:
NameError: name 'obj2' is not defined 我执行了
被动删除:即对象调用完后自动删除
obj2 = Myclass('cc', 22) print(obj2.name) print(obj2.age)
输出:
cc 22 我执行了
3. __getattr__ # 对象查找不存在名字的时候自动触发
class Myclass(object): def __init__(self, name, age): self.name = name self.age = age def __getattr__(self, item): """对象查找不存在名字的时候自动触发""" print('找不到%s 执行__getattr__方法'%item) return '找不到'
obj3 = Myclass('cc', 22) print(obj3.sex)
输出:
找不到sex执行__getattr__方法 找不到
4. __setattr__ # 对象在执行添加属性操作的时候自动触发>>>obj.变量名=变量值
class Myclass(object): def __init__(self, name, age): self.name = name self.age = age def __setattr__(self, key, value): """对象在执行添加属性操作的时候自动触发>>>obj.变量名=变量值""" print('__setattr__方法') print(key, value)
obj4 = Myclass('cc', 22) obj4.sex = 'male'
输出:
__setattr__方法 name cc __setattr__方法 age 22 __setattr__方法 sex male
5. __call__ # 对象被加括号调用的时候自动触发
class Myclass(object): def __init__(self, name, age): self.name = name self.age = age def __call__(self, *args, **kwargs): """对象被加括号调用的时候自动触发""" print('__call__方法', args, kwargs) return '嘿嘿嘿'
obj5 = Myclass('cc', 22) obj5(1, 2, 3, sex='male') print(obj5(1, 2))
输出:
__call__方法 (1, 2, 3) {'sex': 'male'} __call__方法 (1, 2) {} 嘿嘿嘿
6. __enter__ 与 __exit__ # __enter__: 对象被执行with上下文管理语法自动触发 # __exit__: 对象被执行with上下文管理语法结束之后自动触发
class Myclass(object): def __init__(self, name, age): self.name = name self.age = age def __enter__(self): """对象被执行with上下文管理语法自动触发""" print('__enter__方法') def __exit__(self, exc_type, exc_val, exc_tb): """对象被执行with上下文管理语法结束之后自动触发""" print('__exit__方法')
obj6 = Myclass('cc', 22) with obj6 as f: print('执行中') print(123)
输出:
__enter__方法 执行中 __exit__方法 123
7. __getattribute__ # 要对象查找名字无论名字是否存在都会执行该方法 如果类中有'__getattribute__'方法 那么就'不会'去执行'__getattr__'方法
class Myclass(object): def __init__(self, name, age): self.name = name self.age = age def __getattribute__(self, item): """ 只要对象查找名字无论名字是否存在都会执行该方法 如果类中有__getattribute__方法 那么就不会去执行__getattr__方法 """ print('__getattribute__方法', item)
obj7 = Myclass('cc', 22) print(obj7.name) print(obj7.sex)
输出:
__getattribute__方法 name None __getattribute__方法 sex None
个人总结: 有返回值的 即可return __str__: 该方法必须返回字符串类型的数据 对象被print时打印的就是return的值 __call__: 对象被加括号调用的时候自动触发 有返回值,即print(a()) 打印的就是a() 调用时call return的值 __getattr__: 对象查找不存在名字的时候自动触发 找不到可以返回内容 比如提示 __getattribute__: 只要对象查找名字无论名字是否存在都会执行该方法 在查找属性/方法不存在时,抛出AttributeError的异常。如属性或方法存在则返回该属性或方法。
# 元类 即产生类的类 # print(type(123)) # <class 'int'> # print(type([12, 33, 44])) # <class 'list'> # print(type({'name':'jason','pwd':123})) # <class 'dict'> # type查看的其实是当前对象所属的类名称 class MyClass(object): pass obj = MyClass() print(type(obj)) # <class '__main__.MyClass'> print(type(MyClass)) # <class 'type'> class Student: pass print(type(Student)) # <class 'type'> class Teacher(MyClass): pass print(type(Teacher)) # <class 'type'> '''type就是所有类默认的元类!!!'''
1.class关键字 class MyClass(object): pass print(MyClass) # <class '__main__.MyClass'>
2.type元类 type(类名,父类,类的名称空间) res = type('MyClass', (), {}) print(res) # <class '__main__.MyClass'>
元类能够控制类的创建 也就意味着我们可以高度定制类的行为
需要通过关键字参数的形式修改 class C1(metaclass=MyTypeClass): pass
class MyTypeClass(type): def __init__(cls, cls_name, cls_bases, cls_dict): # print(cls, cls_name, cls_bases, cls_dict) if not cls_name.istitle(): raise Exception('类名的首字母必须是大写') super().__init__(cls_name, cls_bases, cls_dict) class C1(metaclass=MyTypeClass): age = 18 class c2(metaclass=MyTypeClass): age = 20 输出: Exception: 类名的首字母必须是大写 # c2小写
1.回想__call__方法 对象加括号会自动执行产生该对象的类里面的__call__,并且该方法返回什么对象加括号就会得到什么 推导:类加括号会执行元类的里面的__call__该方法返回什么其实类加括号就会得到什么
"""类里面的__init__方法和元类里面的__call__方法执行的先后顺序""" class MyTypeClass(type): def __call__(self, *args, **kwargs): print('__call__ run') super().__call__(*args, **kwargs) class MyClass(metaclass=MyTypeClass): def __init__(self, name): print('__init__ run') self.name = name obj = MyClass('cc') 输出: __call__ run __init__ run
# 定制对象的产生过程 class MyTypeClass(type): def __call__(self, *args, **kwargs): # print('__call__ run') # print(args,kwargs) if args: raise Exception('必须全部采用关键字参数') super().__call__(*args, **kwargs) class MyClass(metaclass=MyTypeClass): def __init__(self, name): # print('__init__ run') self.name = name """强制规定:类在实例化产生对象的时候 对象的独有数据必须采用关键字参数""" # obj1 = MyClass('cc') obj2 = MyClass(name='cc') """ 如果你想高度定制类的产生过程 那么编写元类里面的__init__方法 如果你想高度定制对象的产生过程 那么编写元类里面的__call__方法 """
__new__用于产生空对象(类) 骨架 __init__用于实例化对象(类) 血肉 """ 注意:并不是所有的地方都可以直接调用__new__ 该方法过于底层 如果是在元类的__new__里面 可以直接调用 class Meta(type): def __new__(cls, *args, **kwargs): obj = type.__new__(cls,*args,**kwargs) return obj 如果是在元类的__call__里面 需要间接调用 class Mate(type): def __call__(self, *args, **kwargs): obj = object.__new__(self) # 创建一个空对象 self.__init__(obj,*args,**kwargs) # 让对象去初始化 return obj """