python不用显示释放内存,reference count 引用计数,如果不用就减一,当为0的时候,释放内存,refcunt -1。
竞争冒险,进程有多个线程运行,减小不是antomc也即不是原子性,可能会有其他进程插入,无法保证每个object被正常释放。,
解决:加锁,确保程序只有一个线程运行。
- a = 1
- lock.aquire()
- if a > 0:
- a -= 1
GIL是全局锁。只有一个线程锁,避免死锁。
问题有什么,在多核cpu时代。用多进程避开GIL问题。2.自己写cexctention
描述器
- class Name:
- def __get__(self, obj, objtype):
- return "Peter"
- class A:
- name = Name()
- print(A.name)
这个会调用class A的get函数。
- claas Name:
- def __get__(self,obj, objtype):
- return "Peter"
-
- class A:
- def __init__(self):
- self.name = Name()
- o = A()
- print(0.name)
打印的是main的函数初始化的意思。
load_attr,当使用.name,调用description的时候调用load_attr,
装饰器。装饰器就是将函数作为一个对象传入另外一个函数当中进行运算。
在python中函数也是一个对象,所以函数也可以被当作参数传入,calc_number
- def double(x):
- return x ** 2
- def triple(x):
- return x ** 3
- def calu_number(func,x):
- return func(x)
-
- calu_number(double,3)
- calu_number(triple,3)
- # 6 # 9
函数本身也可以作为返回值。
- def calu(n):
- def multiple(x):
- return n * x
- return multiple
- double = calu(2)
- triple =calu(3)
-
- print(doulbe(2))
- print(triple(3))
使用就是
- def dec(f):
- return 1
- @dec
- def f(x):
- return x ** 2
- print(f(x)) # 1
- # 相当于
- def dec(f):
- def f(x):
- return x ** 2
- return 1
所以可以写一些插入相关功能的函数,比如时间装饰器。前面已经写过了。
带参数也是参数先调用一次返回参数,然后这个参数在调用函数。
有模板的,
- import time
- class Timer:
- def __init__(self, func):
- self.func = func
-
- def __call__(self, *args, **kwargs):
- star = time.time()
- ret = self.func(*args, **kwargs)
- print(time.time() - star)
- return ret
- @Timer
- def add(a,b):
- return a+ b
- #d等价于
- add = Timer(add)
- class add_str(cls):
- def __str__(self):
- return str(self.__dict__) # 用字典的形式重载
- cls.__str__ = __str__
- return cls
- @add_str
- class MyObject:
- def __init__(self,a,b):
- self.a = a
- self.b = b
- MyObject = add_str(MyObject)
- o = Myobject(1,2)
- print(o)
- {"a":1,"b":2}
生成器
本身生成器只能用next寻找下一个值,
- a = False
- if a is True:
- return True
- if a == True:
- return True
- if a:
- return True
- if bool(a):
- return True
第二个,==不推荐,已经在python里面可以重载,__eql__,这样导致错误出现。
在源码当中,PyObject_IsTrue。内置数据,如果是数判断是不是0,如果是序列就判断是否是空。如果是自定义的,找是否有__bool__这个属性,如果有的话,调用
- func = lookup_maybe_method(self, &PyId_bool__, &umbound);
- if (func == NULL){
- if (PyErr_Occurred()){
- return -i;
- }
已经是否定义lens,也即判断有没有bool属性或者长度属性,如果都没有,返回1
可以继承其他的方法和数据,printA。python的mro用的是C3算法。
local class walk,
单调性。任何class使用方法来自于直接父类。
建立对象的时候才会出现。也即调用对象的时候才能知道是self.也即实例化类才能调用。
- class A:
- def f(self,data):
- print(self.name)
- print(data)
-
- o = A()
- print(A.f())
- print(o.f())
如果给o赋值o.name = "FS" 调用用的是描述器。
起效果的是function里面的descripe函数。
MethodClass
- class M(type):
- def __new__(cls, name, bases, dict):
- return type.__new__(cls, name, bases, dict)
-
-
- class A(metaclass = M):
- pass
- A = M("A", (),{} )
- o = A()
此处,o =A()会调用A的new 和init函数,当然,A= M(“A“,(),{})的时候,也会调用m的init和new,这个调用是隐式的。
- class M(type):
- def __new__(cls, name, bases, dict):
- return type.__new__(cls, name, bases, dict)
- def __init__(self, name, bases, dict):
- return type.__init__(seflf, name, bases, dict)
- def __new__(cls, name, bases, dict):
- return type.__new__(cls, name, bases, dict)
__new__ 是实例化这个对象,__iniit__ 初始化这个对象。—__call__ 新建的类产生实例的时候调用的。
__slots__ 建立白名单,使得函数更具有健壮性。速度快更加节省内存,
@ super().超类继承关系
当在类中调用关于super()的信息的时候,函数中见的代码变成,在封装的时候,其他人已经做的很好了,我们只要增加一些功能的话,可以直接用super(),继承父类的方法,
- class Animal:
- def __init__(self, age):
- self.age = age
-
- class Person(Animal):
- def __init__(self, age, name):
- self.name = name
- class Male(Person):
- def __init__(self, name , age):
- super(Person, self).__init__(age)
- self.gender = "male"
- m = Male(33,"perter")
- print(m)
super(cls, self) 第一个决定从哪开始找,第二个决定函数对象和mro
- class A:
- def __init__(self):
- print("A")
- class B(A):
- def __init__(self):
- super(B,self).say()
- class C(A):
- def __init__(self):
- print("C")
- class M(B,C):
- def __init__(self):
- B.say(self)
-
- m = M()
- m.say() #C
-
- #因为M 的mro是 BCA 在b上调用self,走的是m的mro,所以从b开始,然后到c,发现直接输出c
在B
- class A:
- @staticmethod
- def F(x):
- print(x)
- A.f(1) # 1
可以将功能绑定在类上,而不是类的对象上很有用,虽然同样可以在类的对象上调用这个方法。,
- class A:
- @classmethod
- def F(cls,x):
- print(cls,x)
- A.f(1) #
1
会把class当作第一个对象传进来。
在python退出的时候,运行一些代码。
- import atexit
- def f():
- print(""exit")
- atexit.register(f)
- 或者在register传入参数。
- @atexit.register
- def f():
- print("exit")
- atexit.unregister(f)
在系统里面有一个block和一个pool
为了创建数据的时候,以后还记得自己创建的数据是什么意思,这里有一个很好的数据结构是nametuple,意味着数据的描述很有用,使用数据结构的时候,对数据的分析在于是否能表达完全,。
比如设置坐标的时候,nametuple的作用就显而易见。
- from collections import namedtuple
-
- # 定义一个namedtuple类型plor,并包含name,sex和age属性。
- User = namedtuple('Plor', ['x', 'y'])
-
- #赋值
- User = User(x = '22', y = '23')
- #或者用一个列表
- User= User._make(['22','23'])