面向对象OOP
面向对象
什么是面向对象:
是一种编程思想,核心是对象,程序就是一系列对象的集合,程序员负责调度控制这些对象来交互着完成任务:
案例: 西天取经
如来有一堆破书要传出去,他没有自己干,而是找了五个对象帮他去干
如来只要负责控制调度的对象即可
如果某个对象发生变化,也不会影响其他的对象,扩展性
类和对象
类和对象
class Person :
pass
p = Person()
属性
"""
属性可以写在类中: 是所有对象公共的
也可以写在对象中: 是每个对象独有的
如果类中和对象中存在同一属性,先访问对象,再访问类
"""
class Person :
"""这是一个人的属性"""
desc = "都会吃饭"
p = Person()
p.name = "李四"
print (p.desc, p.name)
del p.name
p.desc = "喝水"
print (p.desc)
print (p.__dict__)
print (p.__class__)
print (p.__class__.__name)
print (Person.__name__)
__init__方法
"""
__init__方法: 初始化方法,本质上就是一个函数
当实例化对象时,会自动执行__init__方法
会自动将对象作为第一个参数传入,参数名称为self(不建议改)
用于给对象赋初始值
返回值只能是默认的None
"""
class Dog :
def __init__ (self,kind,color ):
print (self)
self.kind = kind
self.color = color
print ("赋值以外的初始化操作" )
d1 = Dog("二哈" ,"黑白" )
print (d1,d1.name,d1.age)
绑定方法和非绑定方法
对象绑定方法
"""
默认情况下类中的方法都是对象绑定方法
特殊之处:
当使用对象调用该函数时会自动传入对象本身,作为该函数第一个参数
当使用类来调用该函数时就是一个普通函数,有几个参数就得传几个参数
"""
class Student :
def __init__ (self,name ):
self.name = name
def say_hi (self ):
print ("hello i am a student! my name: %s" % self.name)
stu1 = Student("jack" ,20 ,"male" )
stu1.say_hi()
Student.say_hi(stu1)
print (type (stu1.say_hi))
print (type (Student.say_hi))
类绑定方法
"""
类绑定方法用 @classmethod 来装饰
特殊之处: 不管用类还是对象调用,都会自动传入类本身,作为第一个参数
什么时候用对象绑定方法: 当函数逻辑需要访问对象中的数据时
什么时候用类绑定方法: 当函数逻辑需要访问类中的数据时
"""
class OldBoyStudent :
def __init__ (self,name ):
self.name = name
@classmethod
def show_school (cls ):
print (cls)
OldBoyStudent.show_school()
print (OldBoyStudent)
非绑定方法
"""
示例: 为学生类添加一个save方法,一个get方法
save: 将对象存储到文件中
get: 从文件中获取对象
"""
import pickle
class Student :
def __init__ (self,name ):
self.name = name
def save (self ):
with open (self.name,"wb" ) as f:
pickle.dump(self,f)
@staticmethod
def get (name ):
with open (name,"rb" ) as f:
obj = pickle.load(f)
return obj
stu = Student("rose" )
stu.save()
obj1 = stu.get("rose" )
print (obj1.name)
obj2 = Student.get("rose" )
print (obj2.name)
继承
继承语法
"""
a继承了b则a就能直接使用b的方法和属性
a称之为子类,b称之为父类或基类
在python中一个子类可以同时继承多个父类
"""
class Base :
desc = "这是一个基类"
def show_info (self ):
print (self.desc)
def make_money (self ):
print ("一天赚一个亿..." )
class SubClass (Base ):
pass
obj = SubClass()
print (obj.desc)
obj.make_money()
抽象
"""
将多个子类中相同的部分进行抽取,形成一个新的类,这个过程称之为抽象
正确使用继承: 先抽象在继承
"""
class Person :
def __init__ (self, name, age, gender ):
self.name = name
self.age = age
self.gender = gender
def say_hi (self ):
print ("name: %s,age: %s,gender: %s" % (self.name,self.age,self.gender))
class Teacher (Person ):
def teaching (self ):
print ("老师教学生写代码..." )
class Student (Person ):
pass
t1 = Teacher("jack" ,20 ,"male" )
t1.say_hi()
stu1 = Student("rose" ,18 ,"female" )
stu1.say_hi()
属性的查找顺序
对象自己的 > 所在类中 > 父类 > 父类的父类 > ... > Object
派生和覆盖
"""
派生:
当子类中出现了与父类中不同的内容时,这个子类就称之为派生类
通常子类都会写一些新的代码,不可能与父类完全一样,既通常都是派生类,所以派生类指的就是子类
覆盖: 也称之为重写,当子类出现了与父类名称完全一致的属性或方法
"""
子类中访问父类的内容
"""
方式1: super(当前类名称,self).要调的父类的属性或方法
方式2: super().要调的父类的属性或方法 # py3的新语法,最常用的方式
方式3: 类名称.要调的父类的属性或方法(self) # 方式3与继承无关,直接指定类名调用
当继承一个现有的类并且覆盖了父类的__init__方法时,必须在__init__方法的第一行调用父类的__init__方法,并传入父类所需的参数
"""
class Parent :
text = "abc"
def say_something (self ):
print ("anything" )
class Sub (Parent ):
def show_info (self ):
print (Parent.text)
Parent.say_something(self)
s = Sub()
s.show_info()
class Person :
def __init__ (self,name,gender,age ):
self.name = name
self.gender = gender
self.age = age
def say_hi (self ):
print ("name: %s, gender: %s, age: %s" % (self.name,self.gender,self.age))
class Student (Person ):
def __init__ (self,name,gender,age,number ):
super ().__init__(name,gender,age)
self.number = number
def say_hi (self ):
super ().say_hi()
print ("numnber: %s" % self.number)
stu = Student("rose" ,"mael" ,20 ,"boy01" )
stu.say_hi()
class MyList (list ):
def __init__ (self,element_type ):
super ().__init__()
self.element_type = element_type
def append (self, object ):
"""
:param object: 要存储的元素
:return: 没有
"""
if type (object ) == self.element_type:
super (MyList,self).append(object )
else :
print ("sorry, your element type not is %s" % self.element_type)
m = MyList(int )
m.append(1 )
print (m[0 ])
m.append("111" )
组合
"""
将一个对象作为另一个对象的属性(既什么有什么)
什么时候用组合: 如果两个类之间完全不属于同类,但需要满足什么有什么
"""
class Phone :
def __init__ (self, kind, color ):
self.kind = kind
self.color = color
def call (self ):
print ("正在呼叫XXX..." )
class Student :
def __init__ (self, name, phone ):
self.name = name
self.phone = phone
phone1 = Phone("apple" , "red" )
stu1 = Student("rose" , phone1)
stu1.phone1.call()
菱形继承
"""
python支持多继承
python3中所有类都直接或间接继承了Object
新式类与经典类:
新式类: 任何显式或隐式的继承自object类就称之为新式类,python3中都是新式类
经典类: 即不是Object的子类,仅在python2中出现
菱形继承时:
新式类: 先深度,当遇到了共同父类时就广度
金典类: 就是深度优先
"""
class A :
pass
class B :
pass
class Test (A,B):
pass
print (Test.mro())
class B :
num = 2
pass
class C :
num = 3
pass
class E (B ):
num = 5
pass
class F (C ):
num = 6
pass
class G (C ):
num = 7
pass
class H (E,F,G):
pass
print (H.num)
print (H.mro())
封装
封装语法
"""
什么是封装: 对外隐藏内部实现细节,并提供访问的接口
什么时候应该封装: 当有一些数据不希望外界可以直接修改时,当有一些函数不希望给外界使用时
被封装内容的特点: 外界不能直接访问,内部依然可以使用
权限: 封装可以控制属性的权限,在python只有两种权限
公开的: 默认就是公开的
私有的: 只能由当前类自己使用
语法: 将要封装的属性或方法名称前加上双下划线
python实现封装的原理:
在加载类的时候,把__替换成了_类名__,替换变量名称
"""
class Person :
def __init__ (self, id_number, name, age ):
self.__id_number = id_number
self.name = name
self.age = age
def show_id (self ):
print (self.__id_number)
p = Person("123456789" , "jack" , 29 )
p.__id_number = "123"
print (p.__id_number)
p.show_id()
class PC :
def __init__ (self,kind,color ):
self.kind = kind
self.color = color
def open (self ):
print ("接通电源" )
self.__check_device()
print ("初始化内核" )
self.__start_services()
print ("启动GUI" )
def __check_device (self ):
print ("硬件检测" )
def __start_services (self ):
print ("启动服务" )
pc1 = PC("苹果" ,"红色" )
pc1.open ()
pc1.__check_device()
class A :
def __init__ (self,key ):
self.__key = key
def key (self ):
return self.__key
a = A("123" )
print (a.__key)
print (a.__dict__)
print (a._A__key)
a.__key = 1
print (a.__dict__)
外界访问私有内容
class Downloader :
def __init__ (self,url,buffer_size ):
self.url = url
self.__buffer_size = buffer_size
def start_download (self ):
if self.__buffer_size <= 1024 *1024 :
print ("开始下载..." )
print ("当前缓冲器大小: " ,self.__buffer_size)
else :
print ("内存炸了..." )
def set_buffer_size (self,size ):
if not type (size) == int :
print ("缓冲区大小必须是整型..." )
else :
self.__buffer_size = size
print ("缓冲区大小修改成功..." )
def get_buffer_size (self ):
return self.__buffer_size
d = Downloader("http: //www.baicu.com" ,1024 *1024 )
d.set_buffer_size(1024 *2048 )
print (d.get_buffer_size())
d.start_download()
property装饰器
"""
通过定义方法来完成对私有属性的访问和修改,给对象的使用者带来了麻烦,必须知道哪些是普通属性哪些是私有属性,需要使用不同的方式来调用他们,property装饰器就是为了使得调用方式一致
使用property装饰器可以将私有属性伪装成普通属性,使得私有属性调用方法跟普通属性一致
property: 用在获取属性的方法上
@属性名.setter: 用在修改属性的方法上
@属性名.deleter: 用在删除属性的方法上
注意: 内部会创建一个对象,对象名称为属性名称,所以在使用setter和deleter时,必须使用对象名称去调用方法
property装饰器还可以用来实现计算属性
计算属性: 属性的值不能直接获得,必须通过计算才能获取,例如: 正方形求面积
"""
class A :
def __init__ (self,name,key ):
self.name = name
self.__key = key
@property
def key (self ):
return self.__key
@key.setter
def key (self,new_key ):
if new_key <= 100 :
self.__key = new_key
else :
print ("key必须小于等于100" )
@key.deleter
def key (self ):
del self.__key
a = A("jack" ,123 )
print (a.key)
a.key = 99
print (a.key)
del a.key
print (a.key)
class Square :
def __init__ (self,width ):
self.width = width
self.area = self.width * self.width
s = Square(10 )
print (s.area)
s.width = 2
print (s.area)
class Square :
def __init__ (self,width ):
self.width = width
@property
def area (self ):
return self.width * self.width
s = Square(10 )
print (s.area)
s.width = 2
print (s.area)
接口
"""
接口是一组功能的集合,接口中仅包含功能的名字,不包含具体的实现代码
接口本质是一套协议标准,遵循这个标准的对象就能被调用
接口方便了对象的使用者,只要学习一套使用方法,就可以以不变应万变
问题: 如果子类没有按照协议来设计,也没办法限制他,将导致代码无法运行
"""
class USB :
def open (self ):
pass
def read (self ):
pass
def write (self ):
pass
def close (self ):
pass
def pc (usb_device ):
usb_device.open ()
usb_device.read()
usb_device.write()
usb_device.close()
class Mouse (USB ):
def open (self ):
print ("鼠标开机..." )
def read (self ):
print ("获取光标位置..." )
def write (self ):
print ("鼠标不支持写入..." )
def close (self ):
print ("鼠标关机..." )
class KeyBoard (USB ):
def open (self ):
print ("键盘开机..." )
def read (self ):
print ("获取按键字符..." )
def write (self ):
print ("键盘敲入代码..." )
def close (self ):
print ("键盘关机..." )
m = Mouse()
pc(m)
k = KeyBoard()
pc(k)
鸭子类型
"""
python一般不会限制你必须怎么写,但作为一个优秀的程序员,就应该自觉遵守相关协议,所以有了鸭子类型这么一说
只要保证你的类按照相关协议类编写,也可以达到提高扩展性的目的
接口是一套协议规范,明确子类应该具备哪些功能
抽象类是用于强制要求子类必须按照协议中规定的来实现
然而python不推崇限制你的语法,可以设计成鸭子类型,既让多个不同类对象具备相同的属性和方法,对于使用者而言,轻松的使用各种对象
"""
def pc (usb_device ):
usb_device.open ()
usb_device.read()
usb_device.write()
usb_device.close()
class Mouse ():
def open (self ):
print ("鼠标开机..." )
def read (self ):
print ("获取光标位置..." )
def write (self ):
print ("鼠标不支持写入..." )
def close (self ):
print ("鼠标关机..." )
class KeyBoard ():
def open (self ):
print ("键盘开机..." )
def read (self ):
print ("获取按键字符..." )
def write (self ):
print ("键盘敲入代码..." )
def close (self ):
print ("键盘关机..." )
m = Mouse()
pc(m)
k = KeyBoard()
pc(k)
抽象类
"""
抽象类(abstract class): 包含抽象方法(没有函数体的方法)的类,
作用: 可以限制子类必须有父类中定义的抽象方法
"""
import abc
class AClass (metaclass=abc.ABCMeta):
@abc.abstractmethod
def run (self ):
pass
class B (AClass ):
def run (self ):
print ("run..." )
b = B()
多态
"""
概念: 多个不同类对象可以响应同一个方法,产生不同的结果,既多个不同类对象有相同的使用方法,
实现多态: 接口、抽象类、鸭子类型都可以写出具备多态的代码
"""
class Ji :
def bark (self ):
print ("咯咯咯" )
def spawn (self ):
print ("下鸡蛋..." )
class Ya :
def bark (self ):
print ("嘎嘎嘎" )
def spawn (self ):
print ("下鸭蛋..." )
class E :
def bark (self ):
print ("饿饿饿" )
def spawn (self ):
print ("下鹅蛋..." )
j = Ji()
y = Ya()
e = E()
def manage (obj ):
obj.spawn()
manage(j)
manage(y)
manage(e)
a = 10
b = "10"
c = [10 ]
print (type (a))
print (type (b))
print (type (c))
OOP相关内置函数
def add_num (a,b ):
if isinstance (a,int ) and isinstance (b,int ):
return a+b
return None
print (add_num(20 ,10 ))
参数一是子类
参数二是父类
class Animal :
def eat (self ):
print ("动物得吃东西..." )
class Pig (Animal ):
def eat (self ):
print ("猪得吃猪食..." )
class Tree :
def light (self ):
print ("植物光合作用..." )
def manage (obj ):
if issubclass (type (obj),Animal):
obj.eat()
else :
print ("不是动物!" )
pig = Pig()
tree = Tree()
manage(pig)
manage(tree)
类中的魔法函数
__str__
"""
执行时机: 在对象被转换为字符串时执行,转换的结果就是__str__函数的返回值
使用场景: 自定义对象的打印格式(print打印会转成字符串,所以会触发__str__)
"""
class Person :
def __str__ (self ):
print ("run" )
return "person"
p = Person()
print (p)
str (p)
print (str (p))
__del__
"""
执行时机: 手动删除对象时立即执行,或是程序运行结束时也会自动执行
使用场景: 当对象在使用过程中,打开了不属于解释器的资源,例如: 文件,网络端口
"""
class Person :
def __del__ (self ):
print ("del run" )
p = Person()
del p
class FileTool :
"""该类用于简化文件的读写操作 """
def __init__ (self,path ):
self.file = open (path,"rt" ,encoding="utf-8" )
def read (self ):
return self.file.read()
def __del__ (self ):
self.file.close()
tool = FileTool("a.txt" )
print (tool.read())
__call__
class A :
def __call__ (self, *args, **kwargs ):
print ("call run" )
print (args)
print (kwargs)
a = A()
a(1 ,a=100 )
__slots__
"""
是一个类属性,用于优化对象内存占用
优化的原理: 固定属性数量,则这个类的对象无法再添加新的属性,解释器不会为这个对象创建名称空间,则没有__dict__
"""
import sys
class Person :
__slots__ = ["name" ]
def __init__ (self,name ):
self.name = name
p = Person("jack" )
print (sys.getsizeof(p))
p.age = 20
print (p.__dict__)
. 语法实现原理
"""
getattr 用 对象.属性 访问属性而属性不存在时执行
setattr 用 对象.属性=值 设置属性时执行
delattr 用 del 对象.属性 删除属性时执行
getattribute 也是用来获取属性,如果属性存在则先执行getattribute再直接返回值,如果属性不存在则先执行getattribute再执行getattr再返回None
"""
class A :
def __getattr__ (self,item ):
print ("__getattr__" )
def __setattr__ (self,key,value ):
print (key)
print (value)
self.__dict__[key] = value
print ("__setattr__" )
def __delattr__ (self,item ):
self.__dict__.pop(item)
print ("__delattr__" )
def __getattribute__ (self,item ):
print ("__getattribute__" )
return super ().__getattribute__(item)
a = A()
a.name = 'jll'
print (a.name)
a.__dict__['age' ] = 18
print (a.age)
del a.name
print (a.name)
b = A()
b.name = 'xxx'
print (b.name)
[] 语法实现原理
"""
任何符号都会被解释器解释成特殊含义,例如: . [] ()
getitem 用中括号获取属性时执行
setitem 用中括号设置属性时执行
delitem 用中括号删除属性时执行
"""
class A :
def __getitem__ (self,item ):
print ("__getitem__" )
return self.__dict__[item]
def __setitem__ (self,key,value ):
print ("__setitem__" )
self.__dict__[key] = value
def __delitem__ (self,key ):
print ("__delitem__" )
del self.__dict__[key]
a = A()
a["name" ] = "jack"
print (a["name" ])
del a["name" ]
class MyDict (dict ):
def __getattr__ (self,key ):
return self.get(key)
def __setattr__ (self,key,value ):
self[key] = value
def __delattr__ (self,key ):
del self[key]
a = MyDict()
a["name" ] = "jack"
print (a["name" ])
print (a.__dict__)
del a["name" ]
a.age = 18
print (a.age)
print (a.__dict__)
del a.age
运算符重载
class Student ():
def __init__ (self,name,height ):
self.name = name
self.height = height
def __gt__ (self, other ):
print ("__gt__" )
return self.height > other.height
def __lt__ (self, other ):
print ("__lt__" )
return self.height < other.height
def __eq__ (self, other ):
print ("__eq__" )
if self.name == other.name and self.age == other.age:
return True
stu1 = Student("jack" ,180 )
stu2 = Student("rose" ,160 )
stu3 = Student("jack" ,180 )
print (stu1 > stu2)
print (stu1 < stu2)
print (stu1 == stu3)
迭代器方法
class MyRange :
def __init__ (self,start,end,step ):
self.start = start
self.end = end
self.step = step
def __iter__ (self ):
return self
def __next__ (self ):
a = self.start
self.start += self.step
if a < self.end:
return a
else :
raise StopIteration
for i in MyRange(1 ,10 ,2 ):
print (i)
上下文管理
"""
在python中,上下文为是一段代码区间,例如: with open打开的文件仅在这个上下文中有效
上下文管理两个方法:
__enter__: 表示进入上下文,应该返回对象自己
__exit__: 表示退出上下文,可以有bool类型返回值,用于表示异常是否被处理,仅在上下文中出现异常有用
如果为True,表示异常已经被处理
如果为False,表示异常未被处理,程序将中断
当执行with语句时,会先执行__enter__,当代码执行完后再执行__exit__,或者代码异常会立即执行__exit__,并传入错误信息(exc_type(包含错误的类型).exc_val(错误的信息).exc_tb(错误的追踪信息))
"""
class MyOpen (object ):
def __init__ (self,path ):
self.path = path
def __enter__ (self ):
self.file = open (self.path)
print ("enter..." )
return self
def __exit__ (self, exc_type, exc_val, exc_tb ):
print ("exit..." )
self.file.close()
with MyOpen("a.txt" ) as m:
print (m.file.read())
反射reflect
反射
"""
反射: 一个对象应该具备检测,增加,修改,删除自身属性的能力,就是通过方法操作对象属性(直接使用__dict__语法繁琐,其实这些方法就是对__dict__的操作进行了封装)
反射的四个内置函数:
hasattr(对象,"属性") 判断对象是否存在某个属性
getattr(对象,"属性") 获取对象属性,可以设置默认值: getattr(对象,"属性",默认值)
setattr(对象,"属性",值) 修改或添加对象属性
delattr(对象,"属性") 删除对象属性
"""
class Person :
def __init__ (self,name,age ):
self.name = name
self.age = age
p = Person("jack" ,18 )
print (hasattr (p,"name" ))
print (getattr (p,"name" ))
print (getattr (p,"names" ,None ))
setattr (p,"name" ,"jll" )
print (p.name)
setattr (p,"id" ,"123" )
print (p.id )
delattr (p,"id" )
反射使用案例:框架
框架代码
"""
框架设计方式:
当对象不是自己写的而是另一方提供的,就必须判断这个对象是否满足要求,是否是我需要的属性和方法
反射被称为框架的基石,因为框架的设计者,不能提前知道你的对象是怎么设计的,所以提供给框架的对象,必须通过检测之后才能使用,检测就是反射要做的事情
示例: 用于处理用户终端指令的小框架
如果框架代码中,写死了使用某个类,这是不合理的,因为无法提前知道框架使用者的类在什么地方类叫什么
所以应该为框架的使用者提供一个配置文件,要求对方将类的信息写入配置文件,然后框架自己去加载需要的模块
如此一来,框架就与实现代码彻底解耦了,只剩下配置文件
"""
import importlib
import settings
def run (plugin ):
while True :
cmd = input ("请输入指令:" )
if cmd == "exit" :
break
if hasattr (plugin,cmd):
func = getattr (plugin,cmd)
func()
else :
print ("该指令不受支持..." )
print ("see you la la!" )
path = settings.CLASS_PATH
module_path,class_name = path.rsplit("." ,1 )
mk = importlib.import_module(module_path)
cls = getattr (mk,class_name)
obj = cls()
run(obj)
插件部分(libs\plugins.py)
class WinCMD :
def cd (self ):
print ("wincmd 切换目录..." )
def delete (self ):
print ("wincmd 删库跑路..." )
def dir (self ):
print ("wincmd 列出所有文件..." )
class LinuxCMD :
def cd (self ):
print ("Linuxcmd 切换目录..." )
def rm (self ):
print ("Linuxcmd 删库跑路..." )
def ls (self ):
print ("Linuxcmd 列出所有文件..." )
配置文件
CLASS_PATH = "libs.plugins.LinuxCMD"
动态导入importlib模块
import importlib
pl = importlib.import_module("libs.plugins" )
cls = getattr (pl,"WinCMD" )
obj = cls()
obj.cd()
元类
"""
元类: 用于创建类的类,万物皆对象,类也是对象,对象是通过类实例化产生的,类对象也是由另一个类实例化产生的,这个类就是元类,默认情况下所有类的元类都是type
"""
class Person (object ):
pass
p = Person()
print (type (p))
print (type (Person))
cls_obj = type ("dog" ,(),{})
print (cls_obj)
自定义元类
"""
元类的作用:创建类对象时做一些限制时可以操作元类,即继承type类来编写自己的元类(只要继承了type就变成了元类),并覆盖__init__方法
"""
class MyType (type ):
def __init__ (self, clss_name, bases, namespace ):
super ().__init__(clss_name, bases, namespace)
print (clss_name, bases, namespace)
if not clss_name.istitle():
raise Exception("类名首字母需大写..." )
class Pig (metaclass=MyType):
pass
class Pig (metaclass=MyType):
pass
元类的__call__方法
"""
当调用类对象(类加括号)时会自动调用元类中的__call__方法,并将这个类作为第一个参数传入
类的元类覆盖byte类的__call__方法后,这个类就无法产生对象,元类必须调用super().__call__来完成对象的创建,并将其对象返回
作用:控制对象的创建过程,可以元类覆盖byte类的__call__方法
"""
class MyMeta (type ):
def __init__ (self,name,bases,namespace ):
super ().__init__(name,bases,namespace)
print ("init run" )
def __call__ (self, *args, **kwargs ):
print ("metaclass call run" )
print (self)
print (args)
print (kwargs)
new_args = []
for a in args:
new_args.append(a.upper())
return super ().__call__(*new_args,**kwargs)
class Dog (metaclass=MyMeta):
def __init__ (self,name,hobby ):
self.name = name
self.hobby = hobby
def __call__ (self, *args, **kwargs ):
print (self)
print ("call run" )
d = Dog("jack" ,"study" )
print (d)
print (d.name,d.hobby)
class Mate (type ):
def __call__ (self, *args, **kwargs ):
if args:
raise Exception("不允许使用位置参数!" )
return super ().__call__(*args,**kwargs)
class A (metaclass=Mate):
def __init__ (self,name ):
self.name = name
a = A(name="jack" )
元类的__new__方法
"""
当创建类对象时,会先执行元类中的__new__方法,拿到一个空对象,再调用__init__来对这个类进行初始化操作(__new__用于创建类对象并且自动调用__init__让对象去初始化)
注意:自定义元类覆盖了__new__方法,则__new__方法必须返回对应的类对象
总结: __new__方法和__init__都可以实现控制类的创建过程,__init__更简单
"""
class Meta (type ):
def __new__ (cls, *args, **kwargs ):
print (cls)
print (args)
print (kwargs)
print ("new run" )
return super ().__new__(cls, *args, **kwargs)
def __init__ (self,a,b,c ):
super ().__init__(a,b,c)
print ("init run" )
class A (metaclass=Meta):
pass
单例设计模式
"""
单例:指的是一个类产生一个对象
为什么要使用单例:单例是为了节省资源,当一个类的所有对象的属性全部相同时,则没有必要创建多个对象
"""
class Single (type ):
def __call__ (self, *args, **kwargs ):
if hasattr (self,"obj" ):
return getattr (self,"obj" )
obj = super ().__call__(*args,**kwargs)
self.obj = obj
print ("new 了" )
return obj
class Student (metaclass=Single):
def __init__ (self,name ):
self.name = name
Student("jll1" )
Student("jll2" )
class Mysql :
_instance = None
def __new__ (cls, *args, **kwargs ):
if not cls._instance:
cls._instance = object .__new__(cls, *args, **kwargs)
return cls._instance
a = Mysql()
b = Mysql()
print (a)
print (b)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!