python笔记

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python笔记相关的知识,希望对你有一定的参考价值。

pip install -r requirements.txt
pip freeze > requirements.txt

Stackoverflow上关于python的问题
备忘:

for i, value in enumerate(my_list):
    pass
for name, value in my_dict.items():
    pass
  • 实例有_class_、__dict__属性
  • 类有__name__属性
  • is是对比地址,==是对比值

1.mutableimmutable数据

在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笔记的主要内容,如果未能解决你的问题,请参考以下文章

Python 3学习笔记

Python Tornado初学笔记之表单与模板

常用python日期日志获取内容循环的代码片段

python 有用的Python代码片段

Python 向 Postman 请求代码片段

python [代码片段]一些有趣的代码#sort