1. py2 vs py3
-
字符编码
py2.7: 默认ascii,字符分unicode+str
py3: 默认utf-8:, str+byte -
语法
整除,print,raw_input,
py2.7: range list != xrange 迭代器
py3: range = xrange: 都是迭代器
2. 迭代器 -> 生成器
迭代器: [] 预先分配一块内存存储, 可随意读取;
生成器: 特殊的迭代器,只能迭代一次,调用时内存中存
迭代器概念:迭代器是访问集合元素的一种方式,从集合的第一个元素开始访问,直到所有的元素被访问完结束,顺序不能倒着来。
list,tuple 用index 和 迭代器都可以访问。但对于无法随机访问的数据结构(比如set)而言,迭代器是唯一的访问元素的方式。
next方法:返回迭代器的下一个元素, iter方法:返回迭代器对象本身
for语法糖: for循环内部事实上就是先调用iter()把Iterable变成Iterator在进行循环迭代的。
yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator。
3. 一般函数,classmethod, staticmethod
class method: 不管这个方式是从实例调用还是从类调用,它都用第一个参数把类传递过来
staticmethod 本质跟全局函数一样
foo方法绑定对象A的实例,class_foo方法绑定对象A,static_foo没有参数绑定。
class_foo, static_foo 都可以通过A, a调用,foo只能通过a调用
vs classmethod: classmethod 可以做需要class参与的动作;staticmehod不行
vs normalmethod: staticmethod本质上就是一个函数,调用方式和调用函数一样,不同的是它不关注对象和对象内部属性。
vs 全局函数: 写到外部会混乱,让类不可控。写到类里面可以很好组织代码,可以继承
list, tuple, set
tuple: t = (1,1,2) 可重复,初始化后不能更改,加减
set: 没有重复
In [12]: s = set([1,1,2])
In [13]: s
Out[13]: {1, 2}
In [14]: s.add(3)
In [15]: s
Out[15]: {1, 2, 3}
5. metaclass, new, init
__metaclass__, __new__, __init__
metaclass,直译为元类,简单的解释就是:
当我们定义了类以后,就可以根据这个类创建出实例,所以:先定义类,然后创建实例。
但是如果我们想创建出类呢?那就必须根据metaclass创建出类,所以:先定义metaclass,然后创建类。
Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class
要创建一个class对象,type()函数依次传入3个参数:
- class的名称;
- 继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;
- class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。
6. list, tuple, dict, set
Python中常见的数据结构可以统称为容器(container)。而序列(如列表和元组)、映射(如字典)以及集合(set)是三类主要的容器
关注:索引(indexing)、分片(sliceing)、加(adding)、乘(multiplying)以及检查某个元素是否属于序列的成员。除此之外,还有计算序列长度、最大最小元素等内置函数
6.1 list
l1 = ['hello', 1]
l2 = list('hello') # ['h', 'e', 'l', 'l', 'o']
nums=range(10)
nums[0] # 索引 , l1[-1]
nums[1:5] # [1, 2, 3, 4]
nums[1:] # [1, 2, 3, 4, 5, 6, 7, 8, 9]
nums[-3:-1] # [7, 8]
nums[-3:] # [7, 8, 9]
nums[:] #复制整个序列
str1 = 'Hello'
print len(str1)
print max(str1) # o
print min(str1) # H
In [20]: a = [1,9,3,3,2,2]
In [21]: a.sort()
In [22]: a
Out[22]: [1, 2, 2, 3, 3, 9]
or
In [31]: a = [1,9,3,3,2,2]
In [32]: sorted(a)
Out[32]: [1, 2, 2, 3, 3, 9]
In [33]: a
Out[33]: [1, 9, 3, 3, 2, 2]
In [23]: t = tuple([1,5,2,3,2])
In [28]: t2 = sorted(t)
In [29]: t2
Out[29]: [1, 2, 2, 3, 5]
In [30]: t
Out[30]: (1, 5, 2, 3, 2)
6.2 tuple 【除了创建和增加,其他属性同list】
t1=1,2,3 # t1=tuple([1,2,3]), t2=tuple("jeff")
t2="jeffreyzhao","cnblogs"
t3=(1,2,3,4) # =t3=tuple((1,2,3,4))
t4=()
t5=(1,)
6.3 dict (键可以为任何不可变类型, 列表和集合不能作为字典的键。)
d.update({'a': ord('a')})
d.clear()
d.fromkeys(['a', 'b', 'c']) # Out[16]: {'a': None, 'b': None, 'c': None}
In [19]: d.fromkeys(['a','b','c'], 2) # Out[19]: {'a': 2, 'b': 2, 'c': 2}
d.pop(key[,default]) # 删除字典给定键 key 所对应的值,返回值为被删除的值。key值必须给出。 否则,返回default值。
如果要降序排序,可以指定reverse=True
sorted_x = sorted(x.iteritems(), key=lambda x : x[1])
6.4 set
集合元素的顺序是随意的, 理解集合为没有value的字典
strs=set(['jeff','wong','cnblogs']) # print {'cnblogs', 'jeff', 'wong'}
# 按照value排序
# 默认是升序
In [29]: d = {'a':1, 'b':-7}
In [30]: sorted(d.items(), key=lambda x: x[1])
Out[30]: [('b', -7), ('a', 1)]
# 降序sorted加reverse=True参数
# 按key排序
n [36]: sorted(d.items(), key=lambda x:x[0])
Out[36]: [('a', 1), ('b', -7)]
In [37]: sorted(d.items(), key=lambda x:x[0], reverse=True)
Out[37]: [('b', -7), ('a', 1)]
交集union or &
set3=set1.union(set2)
set3=set1&set2
并集
set3=set1|set2
x - y # 差集
set(['p', 's'])
add和remove
字典的key(集合)是不可变的, 集合本身只能包含不可变值,所以也就不能包含其他集合
set1.add(set2) # TypeError: unhashable type: 'set'
set1.add(frozenset(set2)) # set([1, frozenset([2])])
strs=set(['jeff','wong','cnblogs'])
nums=set(range(10))
7. Python自省
type(),dir(),getattr(),hasattr(),isinstance().
自省(让对象告诉我们他是什么),用于实现在运行时获取未知对象的信息。
访问对象属性/方法:
hasattr(obj, attr) 这个方法用于检查obj是否有一个名为attr的值的属性,返回一个布尔值。
getattr(obj, attr) 调用这个方法将返回obj中名为attr值的属性的值,例如如果attr为’bar’,则返回obj.bar。
setattr(obj, attr, val) 调用这个方法将返回obj中名为attr值的属性的值,例如如果attr为’bar’,则返回obj.bar。
In [43]: class A:
...: _a = None
...: _b = None
...: def f_a():
...: pass
...:
In [44]: a = A()
In [45]: hasattr(a, '_a')
Out[45]: True
In [46]: hasattr(a, 'f_a')
Out[46]: True
8. Python中单下划线和双下划线
- 单下划线函数和变量,用来指定私有,内部用。
- 双下划线
__foo
,解析器用_classname__foo来代替这个名字,以区别和其他类相同的命名.
dir(Test) 时会看到 _Test__x -
__foo__
: Python内部专有
9. format & %
9.1 %
"hi there %s" % name
当 name=(1,2,3)时会抛异常,所以不会出错的方式是:
"hi there %s" % (name,) # 提供一个单元素的数组而不是一个参数
9.2 format
1.通过位置:
print ("{0},{1}".format('lujf',123))
2.通过关键字参数:
print ("{name},{age}".format(name='lujf',age=23))
3.通过下标:
p = ['lujf',23]
print ('{0[0]},{0[1]}'.format(p))
4.通过对象属性
def __str__(self):
return 'This guy is {self.name},is {self.age} old'.format(self=self)
10 缺省参数对函数的绑定
缺省参数在python中是与函数绑定在一起的。
也就是说,一个函数中定义了一个缺省参数,那么这个参数会随着被调用而改变。(一个坑)
在一次调用中改变了缺省参数的值,可能会影响到这个函数的另外一次调用。
def f(a,L=[]):
L.append(a)
print L
f(1) #[1]
f(2) #[1,2]
11. __new__
&& __init__
new是在实例创建之前被调用的,因为它的任务就是创建实例然后返回该实例,是个静态方法
init是当实例对象创建完成后被调用的,然后设置对象属性的一些初始值。
class Book(object):
def __new__(cls, title):
print'__new__'
return super(Book, cls).__new__(cls)
def __init__(self, title):
print'__init__'
super(Book, self).__init__(self)
self.title = title
b = Book('The Django Book')
print(b.title)
12. copy(),deepcopy()
import copy
a = [1, 2, 3, 4, ['a', 'b']] #原始对象
b = a #赋值,传对象的引用
c = copy.copy(a) #对象拷贝,浅拷贝 等价于 c = 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] # b赋值,跟赋值的list走(包括里面的二层list)
c = [1, 2, 3, 4, ['a', 'b', 'c']] # 浅拷贝,拷贝的list外层,不会改变。里面二层list会变。
d = [1, 2, 3, 4, ['a', 'b']] # 深拷贝,所有的值完全拷贝一份。
a = [1,2]
b=a
a = [3,4]
# a = [3,4]
# b = [1,2] b赋值,跟赋值的list走(包括里面的二层list)
13. 读取文件
read 读取整个文件。
readline 读取下一行,使用生成器方法。
readlines 读取整个文件到一个迭代器以供我们遍历。
14. 新式类和旧式类
- 新式类是在创建的时候继承内置object对象(或者是从内置类型,如list,dict等),而经典类是直接声明的
- 新式类,有
__new__,__init__
等magic method - 新式类有static_method, class_method, 等
- 多重继承的问题: 新式类是广度优先,旧式类是深度优先
网友评论