python学习笔记
python:
可变参数表示:def calc(*numbers): 参数可以传入任意个
参数默认值:def enroll(name, gender, age=6, city='Beijing'):
关键字参数:def person(name, age, **kw):
调用:person('Adam', 45, gender='M', job='Engineer')
2.7不支持:3.0以上支持
命名关键字参数:def person(name, age, *, city, job):
关键字参数只接受“city”,“job”
高阶函数:
即:函数可以当作参数传入另外一个函数中
例如:
def add(x, y, f):
return f(x) + f(y)
函数名称也是一个变量,它指向函数对象本身,
例如:abs()函数 abs = 10以后,abs(10)就无效了
装饰器(Decorator):decorator就是一个返回函数的高阶函数**只要是装饰器必须返回函数**
通常写法:
def log(func):
//包装
def wrapper(*args, **kw):
//相关的逻辑
print 'call %s():' % func.__name__
//返回原始函数
return func(*args, **kw)
//返回包装
return wrapper
with语句:
with定义在类上,且该类必须实现__enter__(),__exit__()两个方法
写法如下:
class Ctx(object):
def __enter__(self):
print '__enter__'
//退出方法要接受四个参数
def __exit__(self,e_t, e_v, t_):
print '__exit__'
def test():
with Ctx():
print '....'
with语法调用顺序:__enter__() => 调用with语句函数的业务逻辑 => __exit__()方法
map(),reduce()函数:
map(fn(),args):即所有的参数都传入fn()函数中,返回list结果,list里面是fn返回的结果集
reduce(fn(x,y),args) reduce函数接受两个参数,其结果作为下一个fn(x,y)的第一个参数,以此类推计算结果
匿名函数:关键字lambda表示匿名函数,冒号前面的x表示函数参数。匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。
例如:f = lambda x: x * x
python:private变量和方法用前加“_”表示,Python并没有一种方法可以完全限制访问private函数或变量,但是,从编程习惯上不应该引用private函数或变量
ModelMetaclass(元类):
面向对象中一切都是对象,(类也是“对象”)
*****通常对象都是类创建,但是类也是对象,类是谁创建的呢???*****
创建对象时,先要创建“类”,然后通过“类”的构造方法返回对象;“元类”所起的作用就是在创建对象时先调用“元类”创建类,然后再由该类创建对象
好处:这样可以在创建类时,动态修改类的属性和方法
总结:如果不使用元类创建类时,编译器默认会调用元类“type._new_()”方法创建类,一旦使用元类,就会调用元类创建类,但是元类创建类也是用“type._new_()”,
只不过在调用type._new_()方法前可以对类进行动态修改,从以上看类中的__init__()方法是一个赋值的过程,在调用此方法时对象已经产生了
继承(可以多继承):任何时候,如果没有合适的类可以继承,就继承自object类
class Animal(object):
class Dog(Animal): Dog继承Animal,Animal继承Object
获取对象属性,设置对象属性以及查看对象属性:getattr()、setattr()以及hasattr();python可以动态给对象加入属性和方法,(这就是动态语言和静态语言的最大区别)
**继承与java区别**
python通过多继承,而java则是单继承然后通过实现多个接口,从以上看python不是存粹的面向对象编程;
#父类
class Animal(object):
pass
# 大类:
class Mammal(Animal):
pass
#行为类(Mixin)
class RunnableMixin(object):
def run(self):
print('Running...')
#狗即是动物,也会奔跑的行为
class Dog(Mammal, Runnable):
pass
限制给对象添加属性的方法:
class Student(object):
... __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
@property神奇的功能:
class Student(object):
#可以把方法变成属性使用,方法名“score”即为属性名
@property
def score(self):
return self._score
@score.setter
def score(self, value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score = value
>>> s = Student()
>>> s.score = 60 # OK,实际转化为s.set_score(60)
如果只有@property,没有对应的@property.setter该属性为只读属性
python中集中调试代码的方法:
1.原始prin语句
2.断言,凡是用print来辅助查看的地方,都可以用断言(assert)来替代:
assert n != 0, 'n is zero!'
取消代码中的断言语句:python -O err.py
3.把print替换为logging是第3种方式,和assert比,logging不会抛出错误,而且可以输出到文件:
logging的好处,它允许你指定记录信息的级别,有debug,info,warning,error等几个级别
当我们指定level=INFO时,logging.debug就不起作用了。同理,指定level=
logging的另一个好处是通过简单的配置,一条语句可以同时输出到不同的地方,比如console和文件。
序列化:
Python提供两个模块来实现序列化:cPickle和pickle,这两个模块功能是一样的,区别在于cPickle是C语言写的,速度快,pickle是纯Python写的,速度慢
对象序列化文件中:
>>> d = dict(name='Bob', age=20, score=88)
>>> f = open('dump.txt', 'wb')
>>> pickle.dump(d, f)
>>> f.close()
反序列化:
>>> f = open('dump.txt', 'rb')
>>> d = pickle.load(f)
>>> f.close()
>>> d
python的多进程与多线程:
多进程:
通过导入模块from multiprocessing import Pool实现
例如:
p = Pool(5)
for i in range(5):
p.apply_async(long_time_task, args=(i,))
print 'Waiting for all subprocesses done...'
p.close()
p.join()
多线程:
通过导入模块import threading
python导入自定义模块:
指定包名下的.py文件(一个模板);
例如:from transwarp.db import Dict 导入包名下db.py模板里面的Dict对象;
注意****是包名而不是文件名*****
包名和文件夹的区别:包名下有__init__.py文件,而文件夹没有
导入自定义文件可以有几种方式:
第一种:在python 安装目录的site-package文件夹中新建xxx.pth,内容是需要导入的package所在的文件夹路径。
第二种:设置环境变量PYTHONPATH: 要导入模块的绝对路径包名