您的位置:首页 > 编程语言 > Python开发

python 的一些知识点(列表解析、打包、装饰器、type、slots)

2012-10-03 19:32 429 查看
8进制:在数字前加数码0,16进制:加0x(数码0与字符x,大小写均可)

>>> a=011

>>> a

9

>>> a=0x11

>>> a

17

由22/-10 =-3 和 -22/10 =-3 和 22/10 =2可以看出,python的取整是类似于地板函数的。

Python 的列表解析(list comprehension)和生成器表达式(generator expression)

以下很多转载自/article/5757473.html

列表解析

在需要改变列表而不是需要新建某列表时,可以使用列表解析。列表解析表达式为:

[expr for iter_varin iterable]

[expr for iter_varin iterable if cond_expr]

第一种语法:首先迭代iterable里所有内容,每一次迭代,都把iterable里相应内容放到iter_var中,再在表达式中应用该iter_var的内容,最后用表达式的计算值生成一个列表。

第二种语法:加入了判断语句,只有满足条件的内容才把iterable里相应内容放到iter_var中,再在表达式中应用该iter_var的内容,最后用表达式的计算值生成一个列表。

>>> num = [j for i in range(2, 8) for j in range(i*2, 50, i)]
>>> num
[4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 10, 15, 20, 25, 30, 35, 40, 45, 12, 18, 24, 30, 36, 42, 48, 14, 21, 28, 35, 42, 49]


生成器表达式

生成器表达式是在python2.4中引入的,当序列过长, 而每次只需要获取一个元素时,应当考虑使用生成器表达式而不是列表解析。生成器表达式的语法和列表解析一样,只不过生成器表达式是被()括起来的,而不是[],如下:

(exprfor iter_varin iterable)

(expr for iter_varin iterableif cond_expr)

例:

>>> L= (i +1for i in range(10) if i %2)
>>> L
<generator object <genexpr> at 0xb749a52c>
>>> L1=[]
>>>for i in L:
... L1.append(i)
...
>>> L1
[2, 4, 6, 8, 10]
可以用L.next()来迭代这个生成器表达式。如果L.next()到边界了会产生一个StopIteration异常。

生成器表达式并不真正创建数字列表, 而是返回一个生成器,这个生成器在每次计算出一个条目后,把这个条目“产生”(yield)出来。 生成器表达式使用了“惰性计算”(lazy evaluation,也有翻译为“延迟求值”,我以为这种按需调用call by need的方式翻译为惰性更好一些),只有在检索时才被赋值(evaluated),所以在列表比较长的情况下使用内存上更有效。A
generator object in python is something like a lazy list. The elements are only evaluated as soon as you iterate over them.

一些说明:

3. 当序列过长, 而每次只需要获取一个元素时,使用生成器表达式。

4. 列表解析的性能相比要比map要好,实现相同功能的for循环效率最差(和列表解析相比差两倍)。

5. 列表解析可以转换为 for循环或者使用map(其中可能会用到filter、lambda函数)表达式,但是列表解析更为简单明了,后者会带来更复杂和深层的嵌套。

作用域

>>> d={'a':1,'b':2}
>>> def f():
print d
def innerf():
print d
d['a']+=1
print d
return innerf

>>> f()
{'a': 1, 'b': 2}
<function innerf at 0xb58351b4>
>>> f()()
{'a': 1, 'b': 2}
{'a': 1, 'b': 2}
{'a': 2, 'b': 2}        可以看出字典d在内层函数是可以用的,这是因为字典是可变对象。如果是数值型或者字符串,那就会
引发异常,UnboundLocalError: local variable 'd' referenced before assignment


python 的面向对象
1.类属性__bases__

类属性__bases__是包含子类的所有父类的一个元组,这里的父类的概念不同与基类。比如。类A,B继承于A,C继承于B,D继承于A与B,则C.__bases__是B, D.__bases__是 A、B。

hasattr(object,name) # boolean

getattr(object,name)# 相当于object.name 属性调用 ,这里的object也可以是mudules。比如getattr(sys,'path') <==> sys.path

打包

“打包”描述的是对某个现有对象进行包装的过程,不管这个对象是一个数据类型还是一段代码。包装过程包括添加新内容、删除无用内容、对现有功能进行改进等。

在python中,对一个标准类型进行子类分离或者推导是不允许的。但是我们可以对某个类型打包为类的核心成员,这样新对象的操作行为就模仿所想要保留的原数据类型的操作行为,那些不想要的操作行为可以不要,而且还可以额外新增功能。这个过程叫做“对类型进行打包”

要进行打包,就要定义新的类,让他的实例具有某个标准类型的核心操作行为。“对类型进行打包”又叫做“代表”,“代表”是打包操作的一种形式,它利用已经存在的功能最大限度地重复使用过去编写的代码。

实现代表的一个很关键的地方就是:必须要用一段包含了getattr()内置函数的代码去覆盖掉__getattr__()方法。更确切地说,调用getattr()的目的是获取对象的缺省属性(数据属性或方法)并返回它们以作进一步访问或调用。__getattr__()特殊方法的工作原理是这样的:当需要检索某个属性的时候,系统先在局部属性中着,也就是先从定制属性中开始找;如果找不到,就会调用__getattr__(),再由它调用getattr()获取一个对象的缺省属性。

举个例子。用open打开一个文件,向其中写入字符(a-z)。数据会自动转储为大写的A-Z。

>>> import string
>>> string.upper('s')
'S'
>>> class capOpen():
def __init__(self,fn,model='r',buf=-1):
self.file=open(fn,model,buf)
def __str__(self):
return str(self.file)
def __repr__(self):
return 'self.file'
def write(self,line):
return self.file.write(string.upper(line))
def __getattr__(self,attr):
return getattr(self.file,attr)

>>> f=capOpen('/home/gauss/test','w')
>>> f
self.file
>>> print f
<open file '/home/gauss/test', mode 'w' at 0xb5733650>
>>> f.write('adsf')
>>> f.close()
>>> f.closed
True
>>> f=capOpen('/home/gauss/test','r')
>>> print f.read()
ADSF


file对象
f.tell()#返回打开的文件中的当前位置。
f.seek()#移动文件指针的位置。第二个参数指出第一个参数是什么意思:0表示的移动到一个绝对位置。1表示移动到一个相对位置(从当前位置算起),还有2表示对于文件尾的一个相对位置。
read()#从打开的文件中读取指定个数的字节,并且返回含有读取数据的字符串。如果没有参数某认将从起始位置开始的全部读完。

轻松实现代理访问

>>> import urllib
>>> proxies = {'http': 'http://proxy.example.com:8080/'}
>>> opener = urllib.FancyURLopener(proxies)
>>> f = opener.open("http://www.python.org")
>>> f.read()
也可以给opener添加请求头部信息

在多线程下载的时候,需要用的
opener.addheader(
"Range"
,
"bytes=%d-%d"
%
(
startpoint,
stoppoint
))




装饰器


涉及到
装饰器,感谢http://www.cnblogs.com/huxi/archive/2011/03/01/1967600.html




import time

def timeit(func):
def wrapper():
start = time.clock()
func()
end =time.clock()
print 'used:', end - start
return wrapper

@timeit
def foo():
print 'in foo()'

foo()


python提供了语法糖来精简装饰器的代码,上面的@timeit即是.

内置的装饰器有三个,分别是staticmethod、classmethod和property,作用分别是把类中定义的实例方法变成静态方法、类方法和类属性。由于模块里可以定义函数,所以静态方法和类方法的用处并不是太多,除非你想要完全的面向对象编程。

class Rabbit(object):

def __init__(self, name):
self._name = name

@staticmethod
def newRabbit(name):
return Rabbit(name)

@classmethod
def newRabbit2(cls):
return Rabbit('')

@property
def name(self):
return self._nam


这里定义的属性是一个只读属性,如果需要可写,则需要再定义一个setter:

@name.setter
def name(self, name):
self._name = name


functools模块

2.3.1. wraps(wrapped[, assigned][, updated]):

这是一个很 有用的装饰器。看过前一篇反射的朋友应该知道,函数是有几个特殊属性比如函数名,在被装饰后,上例中的函数名foo会变成包装函数的名字wrapper,如果你希望使用反射,可能会导致意外的结果。这个装饰器可以解决这个问题,它能将装饰过的函数的特殊属性保留。

import time
import functools

def timeit(func):
@functools.wraps(func)
def wrapper():
start = time.clock()
func()
end =time.clock()
print 'used:', end - start
return wrapper

@timeit
def foo():
print 'in foo()'

foo()
print foo.__name__


首先注意第5行,如果注释这一行,foo.__name__将是'wrapper'。另外相信你也注意到了,这个装饰器竟然带有一个参数。实际上,他还有另外两个可选的参数,assigned中的属性名将使用赋值的方式替换,而updated中的属性名将使用update的方式合并,你可以通过查看functools的源代码获得它们的默认值。对于这个装饰器,相当于wrapper = functools.wraps(func)(wrapper)。

2.3.2. total_ordering(cls):

这个装饰器在特定的场合有一定用处,但是它是在Python 2.7后新增的。它的作用是为实现了至少__lt__、__le__、__gt__、__ge__其中一个的类加上其他的比较方法,这是一个类装饰器。如果觉得不好理解,不妨仔细看看这个装饰器的源代码:

53  def total_ordering(cls):
54      """Class decorator that fills in missing ordering methods"""
55      convert = {
56          '__lt__': [('__gt__', lambda self, other: other < self),
57                     ('__le__', lambda self, other: not other < self),
58                     ('__ge__', lambda self, other: not self < other)],
59          '__le__': [('__ge__', lambda self, other: other <= self),
60                     ('__lt__', lambda self, other: not other <= self),
61                     ('__gt__', lambda self, other: not self <= other)],
62          '__gt__': [('__lt__', lambda self, other: other > self),
63                     ('__ge__', lambda self, other: not other > self),
64                     ('__le__', lambda self, other: not self > other)],
65          '__ge__': [('__le__', lambda self, other: other >= self),
66                     ('__gt__', lambda self, other: not other >= self),
67                     ('__lt__', lambda self, other: not self >= other)]
68      }
69      roots = set(dir(cls)) & set(convert)
70      if not roots:
71          raise ValueError('must define at least one ordering operation: < > <= >=')
72      root = max(roots)       # prefer __lt__ to __le__ to __gt__ to __ge__
73      for opname, opfunc in convert[root]:
74          if opname not in roots:
75              opfunc.__name__ = opname
76              opfunc.__doc__ = getattr(int, opname).__doc__
77              setattr(cls, opname, opfunc)
78      return cls


python中的类定义完之后还是可以修改的。比如

>>> class M():
name='gauss'
def say(self):
print self.__class__.name

>>> M().say()
gauss
然后。。

>>> def f(self,b):
print b

>>> M.say=f       #这里也可以M.say=lambda self,b:。。。。。
>>> m=M()
>>> m.say(4)
4


类中的__call__相当于重载了括号运算符

>>> class M():
def __call__(self,b):
print b

>>> m=M()
>>> m(3)
3
>>>


type它也能动态的创建类。type可以接受一个类的描述作为参数,然后返回一个类。(我知道,根据传入参数的不同,同一个函数拥有两种完全不同的用法是一件很傻的事情,但这在Python中是为了保持向后兼容性)

type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))
>>> def f(self,b):
print b


Foo=type('Foo',(),{'say':f})

>>> Foo().say(4)

4



metaclass。元类。元类是用来创建类的东西,再由这个创建类就是我们平常所说的类。关于元类。这篇博文介绍得极其详细,内容易懂。居家旅行必备啊。

__slots__

限制了类中能访问的属性

>>> class T(object):
__slots__=('info')
def __init__(self,info):
self.info=info

>>> t=T('gauss')
>>> t.info
'gauss'
>>> t.a=3

Traceback (most recent call last):
File "<pyshell#32>", line 1, in <module>
t.a=3
AttributeError: 'T' object has no attribute 'a'
>>>
__slots__是一个元组,只有元组里的属性才能被访问,一定要继承object。其实我们知道,python相当之动态,即使一个已经定义了的类还是能修改的,通过type我们还知道python能动态定义类。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: