python笔记
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python笔记相关的知识,希望对你有一定的参考价值。
pip install -r requirements.txt
pip freeze > requirements.txt
for i, value in enumerate(my_list):
pass
for name, value in my_dict.items():
pass
- 实例有_class_、__dict__属性
- 类有__name__属性
- is是对比地址,==是对比值
1.mutable和immutable数据
在python中,strings, tuples, 和numbers是不可更改的对象,而list, dict等则是可以修改的对象。
strings
tuples
numbers
值传递list
dict
引用传递
在函数内部,传进来的参数是对引用的复制。
2.类变量与实例变量:
class Person:
name=[]
p1=Person()
p2=Person()
p1.name.append(1)
print p1.name
print p2.name
print Person.name
>>>[1]
>>>[1]
>>>[1]
3.metaclass
- 一个class的实例的type是该class
- 一个class的type是‘type’
- type是一个metaclass
type是所有对象的元类
type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))
class Foo(object):
bar = True
等价于
Foo = type(‘Foo‘, (), {‘bar‘:True})
>>>print Foo.bar
True
4.类方法与静态方法
def foo(x):
print "executing foo(%s)"%(x)
class A(object):
def foo(self,x):#实例方法
print "executing foo(%s,%s)"%(self,x)
@classmethod
def class_foo(cls,x):#类方法
print "executing class_foo(%s,%s)"%(cls,x)
@staticmethod
def static_foo(x):#静态方法,不需要与class绑定
print "executing static_foo(%s)"%x
a=A()
\ | 实例方法 | 类方法 | 静态方法 |
---|---|---|---|
a = A() | a.foo(x) | a.class_foo(x) | a.static_foo(x) |
A | 不可用 | A.class_foo(x) | A.static_foo(x) |
5.python自省
运行时能够获得对象的类型.比如type(),dir(),getattr(),hasattr(),isinstance().
6.单下划线和双下划线成员方法
class ClassName:
def __init__(self):
self.__superprivate = "Hello" # 解析器用_classname__foo来代替这个名字,以区别和其他类相同的命名.
self._semiprivate = ", world!" # protected member,在外部访问不会报错,但pycharm会警告
mc = ClassName()
print mc._ClassName__superprivate
print mc._semiprivate
print mc.__dict__
>>>Hello
>>>, world!
>>>{‘_ClassName__superprivate‘: ‘Hello‘, ‘_semiprivate‘: ‘, world!‘}
7.格式化输出
- :号后面带填充的字符,只能是一个字符,不指定的话默认是用空格填充
- ^、<、>分别是居中、左对齐、右对齐,后面带宽度
In [15]: ‘{:>8}‘.format(‘189‘)
Out[15]: ‘ 189‘
In [16]: ‘{:0>8}‘.format(‘189‘)
Out[16]: ‘00000189‘
In [17]: ‘{:a>8}‘.format(‘189‘)
Out[17]: ‘aaaaa189‘
In [44]: ‘{:.2f}‘.format(321.33345)
Out[44]: ‘321.33‘
In [5]: ‘{name},{age}‘.format(age=18,name=‘kzc‘)
Out[5]: ‘kzc,18‘
In [54]: ‘{:b}‘.format(17) # 二进制
Out[54]: ‘10001‘
In [55]: ‘{:d}‘.format(17) # 十进制
Out[55]: ‘17‘
In [56]: ‘{:o}‘.format(17) # 八进制
Out[56]: ‘21‘
In [57]: ‘{:x}‘.format(17) # 十六进制
Out[57]: ‘11‘
name = (1,2,3)
"hi there %s" % name
>>>报错
"hi there %s" % (name,)
>>>‘hi there (1, 2, 3)‘
打印带中文的字典:
print json.dumps(cursor.next(), ensure_ascii=False, encoding=‘utf-8‘)
8.生成器
生成器也是迭代器的一种,但是你只能迭代它们一次.原因很简单,因为它们不是全部存在内存里,它们只在要调用的时候在内存里生成
>>> def createGenerator():
... mylist = range(3)
... for i in mylist:
... yield i*i # 调用函数时返回生成器对象
...
>>> mygenerator = createGenerator() # 创建生成器
>>> print(mygenerator) # mygenerator is an object!
<generator object createGenerator at 0xb7555c34>
>>> print mygenerator.next()
0
>>> for i in mygenerator:
... print(i)
1
4
遍历生成器时,首先计算0,然后会在内存里丢掉0去计算1,直到计算完4.
要理解Yield你必须先理解当你调用函数的时候,函数里的代码并没有运行.函数仅仅返回生成器对象,这就是它最微妙的地方.
9.装饰器
# 字体变粗装饰器
def makebold(fn):
# 装饰器将返回新的函数
def wrapper():
# 在之前或者之后插入新的代码
return "<b>" + fn() + "</b>"
return wrapper
# 斜体装饰器
def makeitalic(fn):
# 装饰器将返回新的函数
def wrapper():
# 在之前或者之后插入新的代码
return "<i>" + fn() + "</i>"
return wrapper
@makebold # 后装饰
@makeitalic # 先装饰
def say():
return "hello"
print say()
#输出: <b><i>hello</i></b>
# 这相当于
def say():
return "hello"
say = makebold(makeitalic(say))
print say()
#输出: <b><i>hello</i></b>
10.解包
- 用list中的值作参数时,用*对list解包:func(*my_list)
- 用dict中的值作参数时,用**对dict解包:func(**my_dict)
11.鸭子类型
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。比如在python中,有很多file-like的东西,比如StringIO,GzipFile,socket。它们有很多相同的方法,我们把它们当作文件使用。又比如list.extend()方法中,我们并不关心它的参数是不是list,只要它是可迭代的,所以它的参数可以是list/tuple/dict/字符串/生成器等.鸭子类型在动态语言中经常使用,非常灵活,使得python不想java那样专门去弄一大堆的设计模式。
12.新式类
继承object的类是新式类
1. _new_,__init__方法:
这两个方法是用来创建object的子类对象,静态方法_new()用来创建类的实例,然后再调用_init()来初始化实例。
2. _delattr, _getattribute, __setattr__方法:
对象使用这些方法来处理属性的访问
3. _hash, _repr, __str__方法:
print(someobj)会调用someobj._str_(), 如果_str__没有定义,则会调用someobj._repr(),
_str_()和**_repr_()**的区别:
- 默认的实现是没有任何作用的
- __repr__的目标是对象信息唯一性
- __str__的目标是对象信息的可读性
- 容器对象的_str__一般使用的是对象元素的_repr
- 如果重新定义了_repr,而没有定义_str,则默认调用_str__时,调用的是_repr,也就是说好的编程习惯是每一个类都需要重写一个__repr__方法,用于提供对象的可读信息,而重写__str__方法是可选的。实现__str__方法,一般是需要更加好看的打印效果,比如你要制作一个报表的时候等。
- 可以允许object的子类重载这些方法,或者添加新的方法。
4.__new__来实现Singleton单例模式:
class Singleton(object):
_instance = list()
def __new__(cls): # Singleton类重写的父类object的__new__函数。
if not cls._instance: # 若还没有任何实例
cls._instance.append(object.__new__(cls)) # 生成一个实例
# cls._instance.append(super(Singleton,cls).__new__(cls))
return cls._instance[0] # 返回这个实例
a = Singleton()
b = Singleton()
print id(a)
print id(b)
# a和b指向同一个实例
>>>140097338089808
>>>140097338089808
5.__slots__属性
默认情况下,python对象队象的每个实例(instance)都会有一个字典_dict__来存储该实例的属性,这样做的好处在于运行时期每个对象可以任意设置新的属性。而相对应的坏处是,当创建成百上千个这样的实例的时候回很浪费内存。所以引入_slots,用来指定实例只拥有固定的属性,因此python会给每个实例对象分配固定的内存空间,从而减少内存消耗。而且使用__slots__可以加快属性的访问。
class A:
def __init__(self):
self.x = 1
self.y = 2
class B(object):
def __init__(self):
self.x = 1
self.y = 2
__slots__ = ‘x‘, ‘y‘ # 限制class B的成员只有x,y
a = A()
b = B()
print a.__dict__
>>>{‘y‘: 2, ‘x‘: 1}
print b.__dict__
>>>AttributeError: ‘B‘ object has no attribute ‘__dict__‘
a.z = 3 # ok
b.z = 3
>>>AttributeError: ‘B‘ object has no attribute ‘z‘
使用时__slots__时需要注意的几点:
1. 当一个类的父类没有定义__slots__属性,父类中的__dict__属性总是可以访问到的,所以只在子类中定义__slots__属性,而不在父类中定义是没有意义的。
2. 如果定义了__slots属性,还是想在之后添加新的变量,就需要把‘__dict__‘字符串添加到__slots__的元组里。
3. 定义了__slots__属性,还会消失的一个属性是__weakref__,这样就不支持实例的weak reference,如果还是想用这个功能,同样,可以把‘__weakref__‘字符串添加到元组里。
4. __slots__功能是通过descriptor实现的,会为每一个变量创建一个descriptor。
5. __slots__的功能只影响定义它的类,因此,子类需要重新定义__slots__才能有它的功能。
6.__getattribute__方法
class MyList(list): # 一个没有append方法的list
def __getattribute__(self, item):
if item == ‘append‘:
raise AttributeError, item
return list.__getattribute__(self, item)
a = MyList()
a.append() # AttributeError: append
7.__getitem__方法
要使新式类的对象支持indexing,必须在新式类中显式地定义_getitem_
class MyList(list):
def __getitem__(self, item):
return item
a = MyList()
print a[1] # 1
8.MRO(Method Resolution Order,方法解析顺序)
A[A<br>a] --> B[B]
A --> C[C<br>a]
B --> D[D]
C --> D[D]
A是B和C的父类,D是B和C的子类
obj=D()
obj.a()
obj调用a方法:
经典类的查找顺序为D->B->A->C,深度优先,会调用A的a方法,这是一个bug;
新式类的查找顺序为D->B->C->A,广度优先,会调用C的a方法。
9.调用父类的方法
class A(object):
def foo(self):
print "A‘s foo"
def a(self):
print "A‘s a"
class B(A):
def foo(self):
print "B‘s foo"
super(B, self).foo()
class C(A):
def foo(self):
print "C‘s foo"
super(C, self).foo()
def a(self):
print "C‘s a"
class D(B, C):
def foo(self):
print "D‘s foo"
super(D, self).foo()
obj = D()
obj.a() # C‘s a
obj.foo()
>>>D‘s foo
>>>B‘s foo
>>>C‘s foo
>>>A‘s foo # 采用super可以保证A中的foo只执行一次
10.__new__和__init__的区别
- __new__是一个静态方法,而__init__是一个实例方法.
- __new__方法会返回一个创建的实例,而__init__什么都不返回.
- 只有在__new__返回一个cls的实例时后面的__init__才能被调用.
- 当创建一个新实例时调用_new,初始化一个实例时用_init.
- ps: 使用_metaclass_,__new__和__init__来分别在类创建,实例创建和实例初始化的时候做一些小手脚.
13.作用域
A[本地作用域 Local] --> B[当前作用域被嵌入的本地作用域 Enclosing locals]
B --> C[全局/模块作用域 Enclosing locals]
C --> D[内置作用域 Built-in]
14.filter、map、reduce
>>>a = [1,2,3,4,5,6,7]
>>>b = filter(lambda x: x > 5, a) # 调用一个布尔函数
>>>print b
[6,7]
>>> a = map(lambda x:x*2,[1,2,3])
>>> list(a)
[2, 4, 6]
>>> reduce(lambda x,y:x*y,range(1,4)) # 对一个序列的每个项迭代调用函数,是求3的阶乘
6
15.python拷贝
import copy
a = [1, 2, 3, 4, [‘a‘, ‘b‘]] #原始对象
b = a #赋值,传对象的引用
c = copy.copy(a) #对象拷贝,浅拷贝
d = copy.deepcopy(a) #对象拷贝,深拷贝
a.append(5) #修改对象a
a[4].append(‘c‘) #修改对象a中的[‘a‘, ‘b‘]数组对象
print ‘a = ‘, a
print ‘b = ‘, b
print ‘c = ‘, c
print ‘d = ‘, d
输出结果:
a = [1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘], 5]
b = [1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘], 5]
c = [1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘]]
d = [1, 2, 3, 4, [‘a‘, ‘b‘]]
16.Python 2.7.x 和 3.x 版本的重要区别
以上是关于python笔记的主要内容,如果未能解决你的问题,请参考以下文章