dive into python
静态语言(JAVA,C)
在编译时确定变量类型
动态语言(python,VBScript)
运行时确定变量类型
动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的。
强类型语言(Java,Python)
变量类型总是强制的.如某个变量是整型,那么你就不可以用string的方法去处理,除非你把该变量转换成str
弱类型语言(VBScript)
变量类型可能被忽略.如有个字符串变量'12',整型变量3,你可以直接把这两个变量连接起来变成'123',不需任何转换
def testfun():
"""
this function do nothing , just demostrate the use of the doc string .
"""
pass
testfun.__doc__
导入模块时,python的搜索路径:sys.path以及当前路径
sys.path.append('xxx')添加到搜索路径
假设你有个模块peak.py,当你导入该模块时(import peak)
那么peak.name__就是'peak',但如果你直接运行该模块,那么它的__name__就是__main
built-in modules是用其他语言(通常是C)所编写的,所以不存在其Python 源码
一切皆对象,这里的对象指,你可以给它指定属性和方法(非强制性).
c={'a':1,2:3}
c.contains('a')#是否有key'a'
del c['a']
li=['a','b','c']#list
li.append(1)#在末尾添加新的元素1
li.insert(2,'3')#在索引2位置插入'3'
li.extend(['d','c'])#连接为一个新的list
li.index('a')#返回第一个'a'的索引
li.remove('a')#移除第一个出现的'a'
del li[0]
li.count('a')#返回'a'出现次数
li.pop()#返回li的最后一个元素,并且从li中删除最后一个元素
li.pop(1)
li = li+['c','d']#类似于extend,extend速度更快
li = li*2#等价于li=li+li
t = ('a','b')#tuple,tuple是不可变类型,tuple比list更快,它能保护你的数据不被修改,tuple可作为dict的键,因为它是不可变的
tuple,list,set可相互转换
v = ('a', 'b', 'e')
(x, y, z) = v #把sequence的值一次性赋给不同变量
set()#空集合
a_set={1,2}
a_set.add(4)
a_set.update({2,4,6},[6,7,8])
a_set.discard(2)#丢掉元素2
a_set.remove(2)#丢掉元素2
discard与remove的差异是,若该元素不存在,remove会报异常
union#并集
intersection#交集
a_set.difference(b_set)#在a不在b
symmetric_difference#异或
issubset
issuperset
使用help(module_name)时首先需要import该模块
dir(module_name)查询模块下的函数
查看模块下特定函数信息help(module_name.func_name)
join将liste里的元素连接成一个string
''.join(['asa','b'])#'asab'
','.join(['asa','b'])#'asa,b'
split(对字符串进行分割成一个List)
li = ['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret']
s=';'.join(li)
s.split(';',1)#分割第一个;,后面出现的;不处理
introspection(自省)
#获得指定对象的信息
def info(object, spacing=10, collapse=1):
"""Print methods and doc strings.
Takes module, class, list, dictionary, or string."""
methodList = [e for e in dir(object) if callable(getattr(object, e))]
processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
print("\n".join(["%s %s" %
(method.ljust(spacing),
processFunc(str(getattr(object, method).__doc__)))
for method in methodList]))
str()#可以把任意对象转换成str类型
dir(x)返回对象x的所有属性和方法
任意callable object都有doc string
通过对某一个对象的所有属性调用callable,你可以知道哪些是你所关心的(方法,函数,类),哪些是你可以忽略的(常数,字符串)
getattr(object,name)
python的内置函数均在__builtins__模块
根据不同输入确定不同函数调用
import statsout
def output(data, format="text"):
output_function = getattr(statsout, "output_%s" % format,statsout.output_text)#第三个参数是个默认值如果getattr为空
return output_function(data)
list Filtering
[mapping−expression for element in source−list if filter−expression]
li = ["a", "mpilgrim", "foo", "b", "c", "b", "d", "d"]
[elem for elem in li if len(elem) > 1]
and 和 or执行布尔逻辑演算,它们并不返回布尔值,而是返回它们实际进行比较的值之一.
0,'',[],{},(),None在布尔环境中为假;
如果布尔环境中的所有值都为真,则and返回最后一个值
如果某个值为假,则and返回第一个假值.
如果有一个值为真,or立刻返回该值,如果都为假,则返回最后一个值
g = lambda x : x2
等价于
def g(x):
return x2
通常将lambda用在需要封装特殊的,非重用代码上,避免存在大量的单行函数
str.ljust(n)#该str的长度为n,空格填充
对象和面向对象
python不存在函数重载.所以父类的__init__会被子类的__init__覆盖
专用方法
可以重写专用方法
dict["a"]实际上调用的是dict.getitem('a')专用方法
dict.setitem(key,vlaue)#dict[key]=value
def __repr__(self): return repr(self.data)
#返回字符串表示
def __cmp__(self, dict):
if isinstance(dict, UserDict):
return cmp(self.data, dict.data)
else:
return cmp(self.data, dict)
def __len__(self): return len(self.data)
def __delitem__(self, key): del self.data[key]
#每实例化一次,类属性count+1.类属性是能够被类和类实例所共享的.
class counter(object):
count = 0#类属性,静态变量
def __init__(self):
self.__class__.count +=1
私有
与大多数的语言不同,一个Python函数,方法,或函数是私有,还是公有,完全取决于它的名字
私有方法,属性等只能被类方法访问
以两个下划线开始,它是私有的.其他都是公有的
以两个下划线开始并结束,则是专用的.
str.replace()
re正则表达式模块
s = '100 NORTH BROAD ROAD'
re.sub('ROAD$', 'RD.', s)#'100 NORTH BROAD RD.'
第一个参数'ROAD\('表示 只有当'ROAD'出现在字符串的尾部时才会匹配 'ROAD\)'
只要为字符串添加一个前缀r,这就告诉python,字符串中的所有字符都不转义
\b:单词的边界必须在这里
s='100 BROAD'
re.sub('ROAD$','RD.',s)
re.sub(r'\bROAD\b','RD.',s)
日志logging
Level
DEBUG Detailed information, typically of interest only when diagnosing problems.
INFO Confirmation that things are working as expected.
WARNING An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected.
ERROR Due to a more serious problem, the software has not been able to perform some function.
CRITICAL A serious error, indicating that the program itself may be unable to continue running.
默认是WARNING
import logging
logging.basicConfig(filename='example.log',level=logging.DEBUG)
logging.basicConfig(filename='example.log', filemode='w', level=logging.DEBUG)#覆盖记录
logging.basicConfig(format='%(asctime)s %(message)s',datefmt='%m/%d/%Y %I:%M:%S %p')%显示时间
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')
logging.exception('Got exception on main handler')#异常抛出到log
raise
d=1 if x>0 else 0
liaoxuefeng教程
动态绑定允许创建类实例,或类后再添加新的方法,属性,.这是静态语言很难实现的.
Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性,对继承的子类是不起作用的.除非在子类中也定义__slots__变量
str()方法
class Student(object):
def __init__(self,name):
self.name = name
def __str__(self):#print(Student('Michael))
return 'Student object (name: %s) % self.name'
__repr__ = __str__ #Student('Michael)
#__str__()返回用户看到的字符串,而__repr__()返回程序开发者看到的字符串,也就是说,__repr__()是为调试服务的。
如果一个类想被用于for ... in循环,类似list或tuple那样,就必须实现一个__iter__()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的__next__()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。
class Fib(object):
def __init__(self):
self.a, self.b = 0, 1 # 初始化两个计数器a,b
def __iter__(self):
return self # 实例本身就是迭代对象,故返回自己
def __next__(self):
self.a, self.b = self.b, self.a + self.b # 计算下一个值
if self.a > 100000: # 退出循环的条件
raise StopIteration()
return self.a # 返回下一个值
def __getitem__(self, n):
a, b = 1, 1
for x in range(n):
a, b = b, a + b
return a
def __getattr__(self, attr):
if attr=='score':
return 99
raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr)
def __call__(self):
print('My name is %s.' % self.name)
for n in Fib():
print(n)
要表现得像list那样按照下标取出元素,需要实现__getitem__()方法:
当调用不存在的属性时,比如score,Python解释器会试图调用__getattr__(self, 'score')来尝试获得属性
任何类,只需要定义一个__call__()方法,就可以直接对实例进行调用
class Chain(object):
def __init__(self, path=''):
self._path = path
def __getattr__(self, path):
return Chain('%s/%s' % (self._path, path))
def __str__(self):
return self._path
__repr__ = __str__
Chain().status.user.timeline.list
创建class的方法就是使用type()函数
class Hello(object):
def hello(self, name='world'):
print('Hello, %s.' % name)
print(type(Hello))
print(type(Hello()))
可以通过type函数创建出新的类,通过type()函数创建的类和直接写class是完全一样的,因为Python解释器遇到class定义时,仅仅是扫描一下class定义的语法,然后调用type()函数创建出class。
def fn(self,name):
print(name)
Hello = type('Hello',(object,),dict(hello=fn))
Hello().hello()
metaclass元类,我们可以把类看成是metaclass的实例
所有的错误类型都继承自BaseException
使用try...except捕获错误还有一个巨大的好处,就是可以跨越多层调用
import logging
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
try:
bar('0')
except Exception as e:
logging.exception(e)
main()
print('END')
程序打印完错误信息后会继续执行,并正常退出
调试
print,用print最大的坏处是将来还得删除它.而这可以用assert代替
如果断言失败,assert语句本身就会抛出AssertionError:
更好的方法是logging
单元测试是用来对一个模块,一个函数或者一个类来进行正确性检测的测试工作
#mydict.py
class Dict(dict):#待测类
def __init__(self, **kw):
super().__init__(**kw)
def __getattr__(self, key):
try:
return self[key]
except KeyError:
raise AttributeError(r"'Dict' object has no attribute '%s'" % key)
def __setattr__(self, key, value):
self[key] = value
#mydict_test.py
import unittest
from mydict import Dict
class TestDict(unittest.TestCase):#单元测试
def test_init(self):
d = Dict(a=1, b='test')
self.assertEqual(d.a, 1)
self.assertEqual(d.b, 'test')
self.assertTrue(isinstance(d, dict))
def test_key(self):
d = Dict()
d['key'] = 'value'
self.assertEqual(d.key, 'value')
def test_attr(self):
d = Dict()
d.key = 'value'
self.assertTrue('key' in d)
self.assertEqual(d['key'], 'value')
def test_keyerror(self):
d = Dict()
with self.assertRaises(KeyError):
value = d['empty']
def test_attrerror(self):
d = Dict()
with self.assertRaises(AttributeError):
value = d.empty
if __name__ == '__main__':
unittest.main()
另一种方法是在命令行通过参数-m unittest直接运行单元测试
以test开头的方法就是测试方法,不以test开头的方法不被认为是测试方法,测试的时候不会被执行。

浙公网安备 33010602011771号