面向对象
一定要面向对象编程
1考虑任务需求,将任务划分抽象成大中小类,并确定从属关系,确定类,方法,属性。继承关系,嵌套关系
2从大类开始创建和简单的小的需要确定的方法。
3从实例化的角度同时考虑类的功能和结构等。可以思考继承的方法
4每一种方法都只实现一个简单的功能
5 在面向对象中继承的观念非常重要 其中super
至关重要
super的使用
函数继承父类中的方法
```
class A(object):
def __init__(self):
print("__init__()")
def go(self):
print("go")
clss B(A):
def __init(self):
print("__init__()")
def go(self):
super(B,self).go()
print("go")
```
Python系统运行 与C
Python 可以导入c中的各种库,通过 from ctypes import *
其中 so=cdll.LoadLibrary('./*.so')
c语言的库文件都是以.so
结尾。库文件相当于一个函数,静态库与程序打包成一个整体,动态库是将地址打包到程序中。
在服务器端运行python文件时,引用模块时需要将文件的路径加载到系统中
import sys
sys.path.append('/data/eddie/流量监控/Metis')
py与pyc文件 其实是一样的东西,在执行的时候如果两个文件的修改时间一致则执行pyc文件否则执行py文件pyc文件具有更快的执行速度,并不是所有的py文件都需要生成pyc文件。
在py程序中执行命令行命令需要使用os.system('命令')
使用c程序需要执行编译将.c
文件编译成.o
文件 之后才能运行
当我们需要使用cython的方式写代码时,可以大大提高运行速度,可以直接将代码编译成C代码进行运行。当需要生成使用import
方式调用的软件包时,可以使用cythob的方式进行写代码,通过setup安装生成python包
首先创建一个文件,该文件是.py
文件,也就是需要加速得到代码,使用setup工具将代码变成import包
vim hello.py
在其中写测试代码
print("hello")
vim setup.py
在其中写
from distutils.core import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize("hello.py")
)
保存后,命令行进入setup.py所在目录,并输入python setup.py build_ext --inplace
在函数调用时使用
import hello
在有些情况下我们需要加快速度,可以使用C和python混编,其中在python中的c和和python类似定义的函数使用cdef
,同时变量需要有类型,函数返回值需要有
类型 具体的一些细节可以看这个cython关键字
Python中的装饰器内在装饰器
@装饰器 作用是为已存在的函数添加额外的功能,函数执行前先执行装饰器内容。在Python 中有三个特殊的装饰器 @staticmethod
,@classmethod
,@property
这三个装饰器是python自带的。
@property:将类中的方法像引用字段那样引用
class TestClass:
def __init__(self, name):
self.name = name
@property
def sayHello(self):
print "hello", self.name
cls = TestClass("felix")
print(cls.name)
cls.sayHello
@staticmethod:将类中的方法装饰为静态方法,即类不需要创建实例的情况下,可以通过类名直接引用。到达将函数功能与实例解绑的效果。当看到该类时第一想到可> 通过类名直接调用。同时可以看作是独立的函数使用。
class Test(object):
def __init__(self,name):
self.name=name
print(name)
@staticmethod
def test1(self):
print("test1")
Test.test1()
python与内存
Python的内存机制呈现金字塔形状,-1,-2层主要有操作系统进行操作;2.第0层是C中的malloc,free
等内存分配和释放函数进行操作;3.第1层和第2层是内存池,有Python的接口函数PyMem_Malloc函数实
现,当对象小于256K时有该层直接分配内存;4.第3层是最上层,也就是我们对Python对象的直接操作;
Python在运行期间会大量地执行malloc和free的操作,频繁地在用户态和核心态之间进行切换,这将严
影响Python的执行效率。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块
内存的申请和释放 Python内部默认的小块内存与大块内存的分界点定在256个字节,当申请的内存小于
256字节时,PyObject_Malloc会在内存池中申请内存;当申请的内存大于256字节时,PyObject_Malloc
的行为将蜕化为malloc的行为。当然,通过修改Python源代码,我们可以改变这个默认值,从而改变Python
的默认内存管理行为。
说到内存就不得不说深浅拷贝和赋值,首先赋值是把对象的内存地方复制一份,然后给其他变量,根据这个变量来
修改对象对应也会影响其赋值前的对象。
a=[1,2,3,[4,5]]
b=a
print(id(a)==id(b))
#结果:True
拷贝的意思就是拷贝对象,会生成两份对象也就是占两份内存,但是浅的意思是只拷贝第一层对象。
import copy
a=[1,2,3,[4,5]]
b=copy.copy(a)
print(id(a)==id(b))
#结果:False
print(id(a[-1]==id(b[-1])))
#结果:True
深拷贝就是对对象整体复制,内存会确实占真双份
import copy
a=[1,2,3,[4,5]]
b=copy.deepcopy(a)
print(id(a)==id(b))
print(id(a[-1])==id(b[-1]))
#结果:False Fasle
垃圾回收
在回收机制中有个引用计数器,用来记录对象的引用次数,在python中对象是实际占用内存的东西,每种操作
都会使计数器放生或增或减的效果,当该对象的计算器变为0时系统会删除该对对象。
使计数器变化的操作有:1.对象被创建p = Person()
,增加1;2.对象被引用p1 = p
,增加1;3.对象被
当作参数传入函数func(p)
,增加2,原因是函数中有两个属性在引用该对象;4.对象存储到容器对
象中l = [p]
,增加1 所谓的容器有,字典,list等 除了增操作还有减操作:1.对象的别名被销毁del p
,
减少1;2.对象的别名被赋予其他对象,减少1;3.对象离开自己的作用域,如getrefcount(对象)
方法,每次
用完后,其对对象的那个引用就会被销毁,减少1;4.对象从容器对象中删除,或者容器对象被销毁,减少1 (容器
就是可以存储多个对象的对象)del
删除的只是变量名,而不是对象(数据),它的作用只是减少一次对象引用当应
用次数减小到0时此时会自动回收数据也就是内存,当数据销毁后调用__del__()
函数 ,如果数据不销毁则不调
用该函数。所以del
和__del__()
不同 del负责减1操作 真正负责清理的是__del__
包含这个方法的对象
需要谨慎使用,因为这个变量不会呗循环计数器回收。类似于c++中的析构器。
class test():
def __init__(self):
print("__init__")
def __del__(self):
print('__del__')
a=test()
del(a)
#结果:__init__ __del__ __del__
##查看引用计数
import sys
a=[1,2,3]
a1=a
b=[a,1,2]
del a1 #del 删除的是变量而不是数据 和__del__() 不同
sys.getrefcount(a) #查看引用计数器对某个对象的计数因为是函数所以默认加了1
有些情况下会出现循环引用,此时引用计数器不能变为0 。循环引用发生在容器身上。 要解除循环引用,需要GC机制,
1先找到所有容器。2对每一个容器对象,使用变量gc_refs来记录当前对应的应用个数。3于每个容器对象,找到其
正在引用的其他容器对象,并将这个被引用的容器对象引用计数减去1。经过步骤3后,检查所有容器对象的引用计数,
若为0,则证明该容器对象是由于循环引用存活下来的,并对其进行销毁。本质依然是通过引用计数的机制来回收内存
,如果对象很多也就是内存块很多的话,垃圾回收的过程会很复杂。
当某些内存块M经过了3次垃圾收集的清洗之后还存活时,我们就将内存块M划到一个集合A中去,而新分配的内存都划
合B中去。当垃圾收集开始工作时,大多数情况都只对集合B进行垃圾回收,而对集合A进行垃圾回收要隔相当长一段时
才进行,这就使得垃圾收集机制需要处理的内存少了,效率自然就提高了。在这个过程中,集合B中的某些内存块由于存
间长而会被转移到集合A中,当然,集合A中实际上也存在一些垃圾,这些垃圾的回收会因为这种分代的机制而被延迟
循环引用的情况
import sys
class A():
def __init__(self):
print('A')
def a(self,x):
self.a=x
class B():
def __init__(self):
print('B')
def b(self,x):
self.b=x
test1=A()
test2=B()
test1.a=test2
test2.b=test1
#此时对于A()对象的计数个数为三。当删除test1之后不能使A()的引用计数变为0 所以不会删除内存。
sys.getrefcount(test2)
for中变量对for内函数的作用域
当我们使用for循环创建函数或者对象时,如果使用for内的变量需要考虑作用空间问题
#使用x其实程序是这样执行的首先for然后x最终会变成9,在执行li[0]() 此时x传入函数时是9
li = []
for x in range(10):
#print(x) #在函数没有执行前(li[0]()),for 循环中x已经执行完,x会一直为 9
def fun():
print(x) #一直为 9 ,fun函数在for循环中是没有被调用的
return x
li.append(fun)
print(li) #9
li[0]()
#结果:9
函数内变量对函数内函数的作用域
def aa(n):
def bb(x):
return x+n
return bb
aa(1)(2)
我们思考函数的返回值问题 函数以什么方式将返回值返回给变量
函数的返回值以元组的方式返回给变量,而且是一个元组
def test():
return 1,(2,3)
a,(b,c)=test()
a=test()#虽然有两个返回值但是我们可以使用一个参数接收
特殊符号用法
->: 一般加在一个函数的后面注释函数的输出类型,
def test(x): -> int
return x+2
*:当有变量输入到函数中或者类实例化时,输入的变量要求是单个字符或者数字,但输入是列表或者元组或者字典时可以用 *a 解析
a=[1,2,3]
def test(x,y,z):
return x+y+z
b=test(*a)
** :同上只不过是字典形式
def b(*args,**kwargs):#可变列表和可变词典,且*必须位于**之前 字典必须用=号否则会被认为是args中的元素
print(args) #在变量前加*号表示拆分可迭代对象,
print("----------------")
print(kwargs)
b([1,2,3],3,6,
nb_epoch=2,
batch_size=3,
freeze_layers_number=4)
#结果:([1, 2, 3], 3, 6)
----------------
{'nb_epoch': 2, 'batch_size': 3, 'freeze_layers_number': 4}
条件语句
| 和& 与and和or 的区别当是数值型的时候 前者是按位取后者只看是不是0
print(1|2)
print(1&2)
#结果 按位计算结果,不支持字符串的操作
print(3 and 4) 结果为其中一个数
导包import 和from import
import 和from :import 是文件级别的导入,from只需要到大概的路劲下直接import函数或者类
import package1 #✅
import module #✅
from module import function #✅
from package1 import module #✅
from package1.package2 import #✅
import module.function1 #❌
_init__.py
文件的作用时当使用import时首先执行__init__.py
文件中的东西
字典
字典有很多神奇的特性,具有超强的功能
首先对字典进行索引,在循环的过程中
labeled_data={}
labels={"a":1,"3":3,"4":4}
for (name, i ) in labels.items(): #返回key和value
labeled_data[name]=-1
print(i)
print(labeled_data)
字典的常用方法 获得字典的key 和value
a={'w':1,'e':2}
a.keys() #得到一个特殊类型的数据,该数据可迭代不可索引,可进行类型转化
a.values()#同上
a.iteams()
#得到字典values的方法
a.get('w') 的带value如果key不存在则返回默认值
#删除其中字典
a.pop('w')#如果key不存在会报错
直接迭代字典会得到字典的key值
列表
列表排序是一个非常重要的工作主要用到的函数有sort 和sorted sort默认从小到大,同时会改变原列表
sorted默认是从小到大,会生成新的list,它可以对所有可迭代对象排序,
字符串
a='\nabcdd'
b=a.rstrip().lstrip() #移除字符串前后标志符号 注意不是inplace操作会生成新的字符串返回
b=a.strip(' d') #移除前后固定符号同时移除
b=a.split('b') #对字符串进行切片 #不是inplace操作