【python学习笔记】第3天

继续今天的python学习

昨天学到了类当做装饰器,今天上来学了一个新的概念:元类,什么是元类呢?

在python中,一切皆对象,类也不例外

class Test:
    print("我是对象...")
    def __init__(self):
        self.num = 0

运行结果:
 

我是对象...

可以看出来,在类创建的时候就会打印这样一句话。(看,他都说他是对象了)

在一个类中,我们不仅可以给类的实例对象添加属性,我们还可以直接给类添加属性

Test.number = 0
print(Test.number)

运行结果:

0

那么我们就又要思考一个问题,类是也是对象,那究竟是谁创建的类呢?

我们之前用到过 type() 函数,利用它可以测出我们输入对象的类型,然而它还有一个功能就是创建一个类

'''
type创建类的用法:
type(类名,(父类的元组),{类的属性和方法})
'''

Test = type("Test",(),{}) # 利用type创建一个类

class Test2:
    pass

print(type(Test))
print(type(Test2))

运行结果:

<class 'type'>
<class 'type'>

可以看出来用type创建的类和class是一样的类型,我们把这样可以创建类的类叫做元类。

那么既然有了元类,我们如何在创建类的时候就定义一些方法和属性呢?

class Dog:
    def __init__(self):
        self.name = "WangWang"

def eat(self):
    print("%s 正在吃..."%self.name)

Test = type("Test",(Dog,),{"eat":eat,"age":5}) # 利用type创建一个类

t = Test()
t.eat()
print("%s 的年龄:"%t.name + str(t.age))
print(Test.age) # 在这里的age属于类属性,可以直接通过类名来调用

运行结果:

WangWang 正在吃...
WangWang 的年龄:5
5

那么我们又想思考一个问题,既然是type创建的class,那么是谁创建的type。。。

我们用代码来测试一下

print(type.__class__)
print(Test.__class__)

运行结果:

<class 'type'>
<class 'type'>

噢,原来是type创建的type~

那么我们还有没有其他的方法去创建一个类呢?答案是肯定的,这次我们接触到了__metaclass__属性

def upper_attr(class_name,class_parents,class_attribute):
    # 把非“__”开头的属性的key全部变为大写字母
    the_dict = dict() #创建一个新的属性字典
    for name, value in class_attribute.items():
        if not name.startswith('_'):
            the_dict[name.upper()] = value
        else:
            the_dict[name] = value
    return type(class_name, class_parents, the_dict)

class Myclass(metaclass=upper_attr):
    low = "low"
    high = "high"
    __the_name = "WangWang"
    def show():
        print(Myclass.__the_name)

print(Myclass.LOW)
print(Myclass.HIGH)
Myclass.SHOW()

运行结果:

low
high
WangWang

可以看到,我们用自己的方式创建了类,这就是利用了metaclass属性,这是在python3当中的用法,如果是在python2当中我们就不是在Myclass后面的括号里使用,而是在类中添加属性 __metaclass__ = upper_attr 即可

有兴趣的朋友可以试试,在上面的if语句中如果把一个下划线换成两个下划线,会出现什么样的问题呢?

接下来学习了python当中的 Garbage Collection——简称GC,是python的垃圾回收机制那么python是如何进行垃圾回收的呢?

顾名思义就是python会自动把我们用不到的数据给干掉啦`

首先接触到了两个概念就是小整数对象池和大整数对象池,前者指的是在[-5,257)范围内的整数是python自己创建好地址的,也就是只要我们引用这范围之内的整数,地址都是相同的,而在这个范围之外的整数在大整数对象池当中,每次创建都会有自己独立的地址。对于字符串类型在python中也规定了特殊的地址,相同的字符串共用一个地址。

python的垃圾回收有两种,第一种是引用计数。

python对象每一次被引用的时候计数会+1,当引用计数变为0的时候python解释器会把这个垃圾清理掉,但有时候引用计数并不能让python完全的清理掉垃圾

import gc
class test:
    pass
def reference():
    while True:
        a1 = test()
        a2 = test()
        a1.ref = a2
        a2.ref = a1
gc.disable()
reference()

上面这几行代码在循环中出现了循环引用的问题(引用计数无法变为0),所以python就引入了另外一个垃圾清理的办法,成为python的分代回收,这个机制的原理是将数据串成一条链(generation zero),python会在一定的时间在这条链上检查循环引用的现象,有循环引用的数据的引用计数会-1,下一次检测时如果这些数据的引用计数为0,则会被python干掉。由于产生了循环引用,所以python生成的数据和释放的数据就产生了一个差值,当这个差值达到一定的数目的时候python会将(generation zero)这条链上的引用计数不为0的数据转移到(generation one)这条链上。

上面的例子导入gc模块把垃圾清理机制关闭后程序占用的内存空间飙升,内存不够用者谨慎运行。。。

gc模块中还提供了一些方法

gc.collect() # 手动进行清理垃圾
gc.get_count() # 获取当前的清理计数
gc.get_threshold() # 查看清理计数的阈值
gc.set_threshold(700,10,10) # 设置清理计数的阈值

注意:不要轻易的修改__del__方法,会影响python的垃圾回收机制

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值