网站集群建设相关的招标中央网站seo
元类
类也是对象(属于元类的对象)
#打印字符串(字符串是对象)
print("HelloWorld")
#打印类名,类同样为一个对象
print(Person)
使用动态创建类:
语法:
type(类名,由父类名称组成的元组(可以为空),包含属性的字典(名称和值))
案例1:使用type创建类
Myclass = type("MyClass", (), {})
m1 = Myclass()
print(type(m1))
案例2:使用type创建带有属性(方法)的类
def show(self):print("---num---%d" % self.num)# 使用元类(type)创建类
Test = type("Test", (), {"show": show})
t = Test()
t.num = 100
t.show()
案例3:使用type动态创建一个继承指定类的类
class Animal(object):def __init__(self, color="Yellow"):self.color = colordef eat(self):print("吃掉你")Dog = type("Dog", (Animal,), {})
dog=Dog()
dog.eat()
print(dog.color)
类装饰器
class Test(object):def __init__(self, func):print("---初始化---")print("func name is %s" % func.__name__)self.__func = func# 重写该方法后,对象可以直接进行调用def __call__(self, *args, **kwargs):print("--装饰器中的功能--")self.__func()# @Test等价于test=Test(test)装饰器的特性
@Test
def test():print('--test函数--')test()
class AAA(object):def __init__(self, func):self.__func = funcdef __call__(self, *args, **kwargs):self.addFunc()self.__func()def addFunc(self):print("用户权限验证")print("日志系统处理")@AAA
def text1():print("我是功能1")
对象池
1.数值类型
小整数池:[-5,256]
程序开始时,一次性加载到内存
LEGB(局部变量,闭包中的变量,全局变量,内建变量)全局都是同一个地址
可以用id():或者is 来判断
超过小整数的范围,内存就发生改变了。
大整数池
大整数池默认创建出来,池内为空的,创建一个就会往池中存储一个
字符串
intern机制
每个单词(字符串),不夹杂空格或者其他符号,默认开启intern机制,共享内存,靠引用计数决定是否销毁
垃圾收集
概述:
现在的高级语言如java,c#等,都采用了垃圾收集机制,而不再是c,c++里用户自己管理维护内存的方式。自己管理内存极其自由,可以任意申请内存,但如同一把双刃剑,为大量内存泄漏,悬空指针等bug埋下隐患。
python里一同java一样采用了垃圾收集机制,不过不一样的是:
python采用的是引用计数机制为主,标记-清除和分代收集两种机制为辅的策略。
垃圾回收机制:GC机制
python:
1.引用计数机制为主
如何获取一个对象的引用计数?
sys.getrefcount(a)
刚创建对象引用计数为2
a.增加引用计数操作
1.如果有新的对象使用该对象,+1
2.装进列表+1
3.作为函数参数
b.减少引用计数操作
1.如果有新的对象使用该对象,新对象不在使用-1
2.从列表中移除-1
3.函数调用结束-1
4 del 显示销毁
2.隔代回收为辅助
# -*- coding: utf-8 -*-
import sysclass AA(object):# 创建对象开辟内存时调用def __new__(cls, *args, **kwargs):print("开辟内存空间")print("静态方法类at :%s" % hex(id(cls)))return super(AA, cls).__new__(cls)# 初始化方法def __init__(self):print("创建对象at :%s" % hex(id(self)))# 对象被系统回收之前,会调用该方法def __del__(self):print("%s say bye bye" % hex(id(self)))aa = AA()
print('a的引用计数为:%d' % sys.getrefcount(aa))
b = aa
print('a的引用计数为:%d' % sys.getrefcount(aa))
list1 = [aa]
print('a的引用计数为:%d' % sys.getrefcount(aa))
b = 100
print('a的引用计数为:%d' % sys.getrefcount(aa))
list1.remove(aa)
print('a的引用计数为:%d' % sys.getrefcount(aa))
在 Python 的 __new__
方法中,不能将 cls
改为 self
,原因在于 self
和 cls
在语义和用途上有本质的区别。以下详细解释为什么不能将 cls
改为 self
:
1. self
和 cls
的含义
-
self
:-
self
是一个实例方法的参数,它代表类的实例对象。 -
在实例方法中,
self
是调用该方法的实例对象的引用。 -
例如:
Python复制
class MyClass:def my_method(self):print(self) # self 是当前实例对象 obj = MyClass() obj.my_method() # 输出 obj 的内存地址
在这里,
self
是obj
的引用。
-
-
cls
:-
cls
是一个类方法或静态方法的参数,它代表类本身。 -
在类方法中,
cls
是调用该方法的类的引用。 -
在
__new__
方法中,cls
是正在被实例化的类的引用。 -
例如:
Python复制
class MyClass:def __new__(cls):print(cls) # cls 是 MyClass 类本身return super(MyClass, cls).__new__(cls) obj = MyClass() # 输出 MyClass 的内存地址
-
2. __new__
方法的特殊性
-
__new__
是一个静态方法(虽然没有显式地使用@staticmethod
装饰器,但它本质上是静态方法)。 -
它的目的是创建类的实例,而不是操作类的实例。
-
在
__new__
方法被调用时,类的实例还没有被创建,因此不存在self
。 -
cls
是__new__
方法的第一个参数,它代表正在被实例化的类。
3. 为什么不能将 cls
改为 self
-
语义错误:
-
self
代表实例对象,而__new__
方法的作用是创建实例对象。在实例对象还没有被创建之前,self
是不存在的。 -
如果将
cls
改为self
,会导致代码的语义混乱,无法正确表达__new__
方法的意图。
-
-
运行时错误:
-
Python 的
__new__
方法的签名是固定的,它必须接受cls
作为第一个参数。 -
如果将
cls
改为self
,Python 解释器会抛出错误,因为它无法正确调用__new__
方法。 -
例如:
Python复制
class MyClass:def __new__(self): # 错误:应该使用 clsreturn super(MyClass, self).__new__(self) obj = MyClass()
这将导致以下错误:
TypeError: __new__() takes 1 positional argument but 2 were given
因为 Python 会将类本身作为第一个参数传递给
__new__
方法,而你定义的__new__
方法只接受一个参数self
,导致参数数量不匹配。
-
4. 正确的用法
-
__new__
方法的正确签名是:Python复制
def __new__(cls, *args, **kwargs):# 创建实例的逻辑return super(cls).__new__(cls)
-
cls
是类的引用,用于调用父类的__new__
方法来完成实例的创建。
5. 总结
-
self
用于实例方法,代表类的实例对象。 -
cls
用于类方法和__new__
方法,代表类本身。 -
在
__new__
方法中,必须使用cls
,因为此时实例对象还没有被创建,不存在self
。 -
将
cls
改为self
会导致语义错误和运行时错误。
类方法或静态方法和实例方法的区别是什么
类方法、静态方法和实例方法是 Python 中类的三种不同类型的成员方法,它们在定义、调用方式和用途上都有显著的区别。以下是它们的详细对比:
1. 定义方式
-
实例方法:
-
定义时不需要任何特殊装饰器。
-
第一个参数必须是
self
,表示类的实例对象。 -
示例:
Python复制
class MyClass:def instance_method(self):print("This is an instance method")
-
-
类方法:
-
使用
@classmethod
装饰器定义。 -
第一个参数必须是
cls
,表示类本身。 -
示例:
Python复制
class MyClass:@classmethoddef class_method(cls):print("This is a class method")
-
-
静态方法:
-
使用
@staticmethod
装饰器定义。 -
不需要任何特殊的第一个参数(既不是
self
也不是cls
)。 -
示例:
Python复制
class MyClass:@staticmethoddef static_method():print("This is a static method")
-
2. 调用方式
-
实例方法:
-
必须通过类的实例对象调用。
-
示例:
Python复制
obj = MyClass() obj.instance_method() # 正确 MyClass.instance_method() # 错误,需要实例对象
-
-
类方法:
-
可以通过类本身调用,也可以通过类的实例对象调用。
-
示例:
Python复制
MyClass.class_method() # 正确 obj = MyClass() obj.class_method() # 也正确
-
-
静态方法:
-
可以通过类本身调用,也可以通过类的实例对象调用。
-
示例:
Python复制
MyClass.static_method() # 正确 obj = MyClass() obj.static_method() # 也正确
-
3. 参数传递
-
实例方法:
-
第一个参数
self
是类的实例对象。 -
示例:
Python复制
class MyClass:def instance_method(self):print(self) # 输出实例对象的内存地址 obj = MyClass() obj.instance_method() # 输出 obj 的内存地址
-
-
类方法:
-
第一个参数
cls
是类本身。 -
示例:
Python复制
class MyClass:@classmethoddef class_method(cls):print(cls) # 输出类的内存地址 MyClass.class_method() # 输出 MyClass 的内存地址
-
-
静态方法:
-
不需要任何特殊的第一个参数。
-
示例:
Python复制
class MyClass:@staticmethoddef static_method():print("No special first parameter") MyClass.static_method() # 输出 "No special first parameter"
-
4. 用途
-
实例方法:
-
主要用于操作类的实例对象的属性和方法。
-
通常用于实现类的业务逻辑。
-
示例:
Python复制
class MyClass:def __init__(self, value):self.value = valuedef instance_method(self):print(f"The value is {self.value}") obj = MyClass(10) obj.instance_method() # 输出 "The value is 10"
-
-
类方法:
-
主要用于操作类本身,而不是类的实例对象。
-
常用于实现类级别的逻辑,例如工厂方法、类属性的访问等。
-
示例:
Python复制
class MyClass:count = 0@classmethoddef class_method(cls):cls.count += 1print(f"Class count is {cls.count}") MyClass.class_method() # 输出 "Class count is 1" MyClass.class_method() # 输出 "Class count is 2"
-
-
静态方法:
-
不依赖于类或实例对象的状态。
-
常用于实现与类相关的工具函数或辅助方法。
-
示例:
Python复制
class MyClass:@staticmethoddef static_method(x, y):return x + y print(MyClass.static_method(3, 4)) # 输出 7
-
5. 总结
特性 | 实例方法 | 类方法 | 静态方法 |
---|---|---|---|
定义方式 | 不需要装饰器,第一个参数是 self | 使用 @classmethod ,第一个参数是 cls | 使用 @staticmethod ,无特殊参数 |
调用方式 | 必须通过实例对象调用 | 可以通过类或实例对象调用 | 可以通过类或实例对象调用 |
参数传递 | self 是实例对象 | cls 是类本身 | 无特殊参数 |
用途 | 操作实例对象的属性和方法 | 操作类本身,实现类级别的逻辑 | 实现与类相关的工具函数 |
通过理解这些区别,你可以根据实际需求选择合适的类型的方法来实现类的功能。
隔代回收机制
原理:
随着时间的推进,程序冗余对象逐渐增多,达到一定数量(阈值),系统进行回收
(0代,1代,2代)
代码
# -*- coding: utf-8 -*-
import gc
import timeclass AA(object):def __new__(cls, *args, **kwargs):print("new")return super(AA, cls).__new__(cls)def __init__(self):print("object :born at %s" % hex(id(self)))def __del__(self):print("%s 被系统回收" % hex(id(self)))def start():while True:a = AA()b = AA()a.v = bb.v = adel adel bprint(gc.get_threshold())print(gc.get_count())time.sleep(0.1)start()
在这段代码中,a.v
是对类 AA
的实例对象 a
的一个属性赋值操作。具体来说,a.v
是将实例对象 b
赋值给实例对象 a
的一个属性 v
。