目录:
参照内容:经典Django教程《Python+Django+Web开发指南》
重点概念:
交互解释器tab还是空格对象的布尔值经典除法 真正除法内置数字工厂序列列表,字符串,元组列表推导式生成器表达式不可变字符串指示符内置序列函数表达式 语句匿名函数 lambda垃圾自动回收动态实例属性
Django提供了一个高级的框架,用它只需要很少代码就可以完成一个Web应用。
Django使用Python写成的,Python是一门OOP的开发语言,同时兼具系统语言(C、C++、java)的强大和脚本语言(Ruby和VB)的灵活迅速。
本节主要总结Django工程师一定要知道的Python概念,而不是一份通用的Python教程。
Python Shell中,不用去创建和保存一个源文件,就可以直接把代码拿来测试。
>>> PRint 'Hello world!'Hello World!
来看一个复杂的例子:
ganiks.liu@MAMIS-GAIKS-LIU /E/mysite (master)$ pythonPython 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] on win32Type "help", "copyright", "credits" or "license" for more information.>>> for Word in ['capitalize', 'these', 'words']:... print word.upper() File "<stdin>", line 2 print word.upper() ^IndentationError: expected an indented block>>> for word in ['capitalize', 'these', 'words']:... print word.upper()...CAPITALIZETHESEWORDS>>> for i in rang(0,5):... print i...Traceback (most recent call last): File "<stdin>", line 1, in <module>NameError: name 'rang' is not defined>>> for i in range(0,5):... print i...01234>>>
python语法中重要的一个方面就是没有区分代码库的花括号{ }, 而是用对齐来替代
iPython
iPython
的能力完全是另一个数量级上的解释器。它提供了系统shell访问、命令行技术、自动对齐、命令行历史等许多特性。
要是能在Python的解释器中调试Django应用是不是很酷?
变量和赋值 —— 除非你想解释器询问更多信息,否则你不可能百分百确定变量在任何给定的时刻是什么类型的对象
$ pythonPython 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] on win32Type "help", "copyright", "credits" or "license" for more information.>>> foo = 'bar'>>> foo'bar'>>> type(foo)<type 'str'>>>> foo = 1>>> type(foo)<type 'int'>>>>
条件语句的()
Python的作者:只有干净和容易阅读的代码才能避免混乱
所有的Python值都可以表示为布尔值,这个的用处在哪里?
在于if和while语句里面做条件判断~
>>> download_complete = False>>> bool(download_complete)False>>> bool(-1.2)True>>> bool("")False>>> bool([None])True>>> bool([None, 0])True>>> bool([])False>>>
**python只有一种整数类型**
>>> type(3.75)<type 'float'>>>> type(0377)<type 'int'>>>> type(0xE8C6)<type 'int'>>>> type(2+2j)<type 'complex'>
+
-
*
/
floor division 经典除法(整数相除结果取整,浮点相除结果取浮点)//
true division 真正的除法 (统统取整数结果)&
|
~
^
>>
<<
&=
<<=
关于 /
//
In [8]: 1/2Out[8]: 0In [9]: 1.0/2Out[9]: 0.5In [10]: 1.0/2.0Out[10]: 0.5In [11]: 1/2.0Out[11]: 0.5In [12]: 1//2Out[12]: 0In [13]: 1.0//2Out[13]: 0.0In [14]: 1.0//2.0Out[14]: 0.0In [15]: 1//2.0Out[15]: 0.0In [16]: type(1//2.0)Out[16]: floatIn [17]: type(1//2)Out[17]: int
>>> int('123')123>>> int(45.67)45>>> round(1.15, 1)1.1>>> float(10)10.0>>> divmod(15, 6)(2, 3)>>> ord('a')97>>> chr(65)'A'>>>
序列类型类似其他语言中的数组,不同的是:
常见的序列有:
,
)像数组一样, 序列可以直接索引:
>>> s = 'Python'>>> s[0]'P'>>> s[4]'o'>>> s[-1]'n'
还可以一次索引多个元素,在这里成为序列切片
>>> s[1:4]'yth'>>> s[3:]'hon'>>> s[3:-1]'ho'>>> s[:]'Python'>>> str(s)'Python'
切片语法适用于所有的序列,包括字符串、元组、列表
其他的序列操作符还有连接, 复制, 检查是否是成员
>>> 'Python and ' + 'Django are cool''Python and Django are cool'>>> 'Python and ' 'Django are cool''Python and Django are cool'>>> '-'*40'----------------------------------------'>>> 'an' in 'Django'True>>> 'xyz' in 'Django'False
建避免在序列上使用 + 操作符,因为其效率不高
>>> 'foo'+'bar''foobar'#建议使用下面两种方式>>> '%s%s' % ('foo', 'bar')'foobar'>>> s=''>>> s.join(['foo', 'bar'])'foobar'
>>> book=['python', 'develop', 8]>>> book.append(2008)>>> book.insert(1, 'web')>>> book['python', 'web', 'develop', 8, 2008]>>> book[:3]['python', 'web', 'develop']>>> 'django' in bookFalse>>> book.remove(8)>>> book.pop(-1)2008>>> book['python', 'web', 'develop']>>> book*2['python', 'web', 'develop', 'python', 'web', 'develop']>>> book.extend(['with', 'django'])>>> book['python', 'web', 'develop', 'with', 'django']>>> book.extend([])>>> book.extend(['end'])>>> book['python', 'web', 'develop', 'with', 'django', 'end']>>> book.sort()>>> book['develop', 'django', 'end', 'python', 'web', 'with']
这里注意一点跟string字符串的区别,列表的内置函数如sort, append, insert都是直接对对象进行修改,而没有返回值;字符串比如用upper方法则是返回了一个字符串。
这是因为字符串是不可改变的,而列表可变
python2.4以上版本提供了sorted和reversed方法可以接受一个列表作为参数并返回一个处理过的拷贝
>>> book=['c','b',4,1,'a',2,3]>>> sbook = sorted(book)>>> sbook[1, 2, 3, 4, 'a', 'b', 'c']
>>> data = [x for x in range(10) if x%2 ==0]>>> data[0, 2, 4, 6, 8]>>> data = (x for x in range(100) if x%2 ==0)>>> data<generator object <genexpr> at 0x00DCE710>
如果你的输入序列很大,最好用生成器表达式,节省内存
字符串不能修改,大小也不能改变
任何没有一个能修改现有的对象的方法,只是返回一个修改了的拷贝
到目前为止,已经有超过37个字符串方法
>>> s = 'Django is cool'>>> words = s.split()>>> words['Django', 'is', 'cool']>>> ' '.join(words)'Django is cool'>>> '::'.join(words)'Django::is::cool'>>> s.upper()'DJANGO IS COOL'>>> s'Django is cool'>>> s.upper().isupper()True>>> s.title()'Django Is Cool'>>> s.capitalize()'Django is cool'>>> s.count('o')3>>> s.find('go')4>>> s.find('xxxx')-1>>> s.startswith('Python')False>>> s.startswith('Django')True>>> s.replace('Django', 'Python')'Python is cool'>>>
>>> mystr = u'This is Unicode'>>> mystru'This is Unicode'>>> print mystrThis is Unicode>>> filename = 'C:/temp/newfolder'>>> filename'C:/temp/newfolder'>>> print filenameC: empewfolder>>> filename = r'C:/temp/newfolder'>>> print filenameC:/temp/newfolder#为了保持一致,所有的正则表达式都要用raw指示符>>> regex = "/w+@/w+/./w+">>> print regex/w+@/w+/./w+>>> regex = r"/w+@/w+/./w+">>> print regex/w+@/w+/./w+
通常Python字符串都只含有很少字符,不足以显示更多的非英文字符。而Unicode是新型的字符集,拥有大量的编码方式,不存在这个显示。
>>> str = "中国">>> str'/xd6/xd0/xb9/xfa'>>> str = u"中国">>> stru'/u4e2d/u56fd'>>> str = r"中国">>> str'/xd6/xd0/xb9/xfa'>>> print str中国>>> str = u"中国">>> print str中国>>> str = "中国">>> print str中国
>>> s = 'Django is cool'>>> '%s is number %d' % (s[:6], 1)'Django is number 1'>>> hi = '''hi... there'''>>> hi'hi/nthere'>>> print hihithere
展示一个高级应用的实例
>>> xml = '''... <?xml version="1.0"?>... <request version="%.1f">... <Data>... <Payload>%s</Payload>... </Data>... </request>... '''>>> VERSION = 1.2>>> payload = 'super top-secret info'>>> print (xml %(VERSION, payload))<?xml version="1.0"?><request version="1.2"> <Data> <Payload>super top-secret info</Payload> </Data></request>
表明上元组和列表只是用什么括号() []
的区别,深层次的区别则要说道Python的对象模型。
列表允许改变值,元组不可以!(像字符串)所以元组没有方法。
但是元组也不单单是一个只读列表,元组的主要作用是作为参数传递给函数调用,或是从函数调用那里获取参数时, 保护其内容不被外部接口修改。
所以元组在前台的用武之地不大,但是在后台却很频繁使用,例如Django的配置文件中的admin选项、URLconf规则、settings.py配置。
!!! 单个元素的元组要求在最后“必须”跟一个逗号,元组是逗号决定的,而不是小括号。
>>> a = ("one", "two")>>> a('one', 'two')>>> type(a)<type 'tuple'>>>> a[0]'one'>>> a = ('just-one')>>> a'just-one'>>> type(a)<type 'str'>>>> c = ('just-one',)>>> c('just-one',)>>> type(c)<type 'tuple'>>>> d = "just-one",>>> d('just-one',)>>> type(d)<type 'tuple'>
>>> a=("one","two")>>> type(a)<type 'tuple'>>>> a('one', 'two')>>> len(a)2>>> max(a)'two'>>> sorted(a)['one', 'two']>>> sum(a)Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: unsupported Operand type(s) for +: 'int' and 'str'>>> any(a)True>>> zip(a, a)[('one', 'one'), ('two', 'two')]>>> b=list(a)>>> b['one', 'two']>>> c=str(a)>>> c"('one', 'two')">>> sum(b)Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: unsupported operand type(s) for +: 'int' and 'str'
字典是Python中唯一的映射类型,可变的,无序的,大小可变的键值映射;别名散列表(hashes)
关联数组
虽然语法跟序列相似,但是用键
而不是下标
来访问元素;而且定义的话使用的花括号{ }
>>> book = {'title':'Python Web Dev', 'year':2008}>>> book{'year': 2008, 'title': 'Python Web Dev'}>>> type(book)<type 'dict'>>>> 'year' in bookTrue>>> book.get('pub')>>> book.get('pub', 'N/A')'N/A'>>> book['pub']Traceback (most recent call last): File "<stdin>", line 1, in <module>KeyError: 'pub'>>> book['pub']='Addision Wesley'>>> book['pub']'Addision Wesley'>>> book.get('pub', 'N/A')'Addision Wesley'>>> for key in book:... print key, ':', book[key] File "<stdin>", line 2 print key, ':', book[key] ^IndentationError: expected an indented block>>> for key in book:... print key, ':', book[key]...year : 2008pub : Addision Wesleytitle : Python Web Dev>>> book.setdefault('price', 100.00)100.0>>> book{'price': 100.0, 'year': 2008, 'pub': 'Addision Wesley', 'title': 'Python Web Dev'}>>> del book['price']>>> book{'year': 2008, 'pub': 'Addision Wesley', 'title': 'Python Web Dev'}>>> book['title']='Python Web Dev with Django'>>> book{'year': 2008, 'pub': 'Addision Wesley', 'title': 'Python Web Dev with Django'}>>> len(book)3
Django 中类似字典的数据类型,Request对象和Response对象
list
和字典dict
是应用的最频繁的数据类型data = raw_input("Enter y or n :")if data[0] == 'y': print "you enter y"elif data[0] == 'n' : print "you enter n"else print "invalid"
for
>>> i = 0>>> while i < 5:... print i... i += 1...01234
更常用的是for
循环,这个for循环更像是shell中的foreach,让你专注于问题本身而不担心计数变量。
for line in open('/tmp/some_file.txt') if 'error' in line: print line
还记得列表推导式吗?
data = [x for x in range(10) if x%2 ==0]
当然如果你还是要在循环的同时计数的话,可以使用内置函数enumerate
(for循环自身没办法计数)
>>> for i, value in data:... print i...Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: 'int' object is not iterable>>> for i, value in data:... print value...Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: 'int' object is not iterable>>> for value in data:... print value...123abc3.14
>>> data = (123, 'abc', 3.14)>>> for i, value in enumerate(data):... print i, value...0 1231 abc2 3.14>>>
enumerate
特别是在用到choices
参数的地方
STATUS_CHOICES = enumerate(("solid", "liquid"))class IceCream(models.Model): falvor = models.CharField(max_length = 50) status = models.ItergerField(choices = STAUTS_CHOICES)
在数据库里, 你的IceCream的status值被保存为整数(0, 1, 2), 但是在Django的admin界面中显示的确实是文字标签。
这样利用数据库存储的效率高,而且???当出现字符无法按照预想顺序排序的时候也比较方便。
Python的try-except语句跟其他语言的try-catch结构相似;
运行时发生异常的话, 解释器会找相应的处理语句handler;
要是在当前函数没有找到,会将异常传递到上层函数;
如果到最外层全局main还是没有找到,解释器会退出,同时打印traceback以便让用户找出错误。
异常处理可以处理从简单的单个异常到一系列的多个不同的异常类型。
try: f = open(filename, 'r')except IOError, e: return False, str(e)
同一段处理语句也可以处理多个异常类型,只要放在一个元组中即可
try: process_some_data()except (TypeError, ValueError), e: print "Error: you provide invalid data", e
或者为多个异常创建多个处理语句:(有点像swithc case break)
try: process_some_data()except (TypeError, ValueError), e: print "ERROR: invalid data", eexcept ArithmeticError, e: print "ERROR: some math error", eexcept Exceptioin, e: print "ERROR: invalid data", e
Python还提供了一个 finally自居,无论错误是不是发生,这些代码都必须运行,比如关闭文件,释放锁, 把数据库连接返回给连接池。
try: get_mutex() do_some_stuff()finally: free_mutex()
自Python2.5之后,try-finally 可以跟 except 一起使用。
try: get_mutex() do_some_stuff()except (IndexError, KeyError, AttributeError), e: log("ERORR:...")finally free_mutex()
def foo(must_be_positive_int) if not isinstance(must_be_positive_int) raise TypeError("ERROR foo(): must pass in an integer") if must_be_positive_int < 1: raise ValueError("ERROR foo(): ...")
more refert to : https://docs.python.org/2.7/library/exceptions.html
>>> f = open('test.txt', 'w')>>> f.write('foo/n')>>> f.write('bar/n')>>> f.close()>>> dir<built-in function dir>>>> f = open('test.txt', 'r')>>> for line in f:... print line.rstrip()...foobar>>> f = open('test.txt', 'r')>>> for line in f:... print line...foobar
除了read 和 write 方法还有 readlines 和 writelines 方法,让文件跟列表list
打交道
>>> f = open('test.txt', 'r')>>> f.read()'foo/nbar/n'>>> f = open('test.txt', 'r')>>> f.readlines()['foo/n', 'bar/n']>>> f = open('test.txt', 'w')>>> f.writelines(['foo', 'bar'])>>> f = open('test.txt', 'r')>>> f.read()'foobar'
重点
)>>> def foo(x):... print x...>>> foo(123)123>>> import httplib>>> def check_web_server(host, port, path):... h = httplib.HTTPConnection(host, port)... h.request('GET', path)... resp = h.getresponse()... print 'HTTP Response:'... print ' status = ', resp.status... print ' reason = ', resp.reason... print 'HTTP Headers: '... for hdr in resp.getheaders():... print ' %s: %s' %hdr...>>> check_web_server('www.python.org', 80, '/')HTTP Response: status = 301 reason = Moved PermanentlyHTTP Headers: content-length: 0 via: 1.1 varnish x-cache: MISS accept-ranges: bytes strict-transport-security: max-age=63072000; includeSubDomains server: Varnish retry-after: 0 connection: close x-served-by: cache-ty67-TYO x-cache-hits: 0 location: https://www.python.org/ date: Wed, 24 Sep 2014 06:38:42 GMT>>> check_web_server('www.baidu.com', 80, '/')HTTP Response: status = 200 reason = OKHTTP Headers: content-length: 14613 bdqid: 0xa15e849b0000a0cc set-cookie: BAIDUID=C888FD3659C854691DC8B775D3D3C55E:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com, BDSVRTM=0; path=/ accept-ranges: bytes vary: Accept-Encoding bduserid: 0 server: BWS/1.1 last-modified: Wed, 03 Sep 2014 02:48:32 GMT connection: Keep-Alive pragma: no-cache cache-control: no-cache date: Wed, 24 Sep 2014 06:39:17 GMT p3p: CP=" OTI DSP COR IVA OUR IND COM " content-type: text/html bdpagetype: 1>>>
调用的时候,我们需要记得函数定义中的参数顺序:host, port, path
那如果没有记得呢,可以用关键字参数,也是ok的
>>> check_web_server(path='/', port=80, host='www.baidu.com')
定义函数的时候,Python同样支持默认参数的定义
>>> def check_web_server(host, port=80, path='/')
注意, 所有必须提供 的参数必须出现在可选参数之前,下面就是错误的
>>> def check_web_server(path, port=80, host) #INVALID
危险
因为列表和字典是可变的,当他们持续穿过多个函数调用时
>>> def func(arg=[]):... arg.append(1)... print arg...>>> func()[1]>>> func()[1, 1]>>> func()[1, 1, 1]>>> func()[1, 1, 1, 1]
对象引用
在Python里面,你可把函数和方法当做和其他对象一样的使用
只有当我们要调用函数的时候才会加上小括号()
, 在把它当做变量或者对象传来传去的时候,只需要用函数的名字就好。
这将引用bar
和调用bar()
区分开来
>>> def bar():... print "bar"...>>> bar()bar>>> baz = bar>>> baz()bar>>>>>>>>> function_list = [bar, baz]>>> for function in function_list:... function()...barbar
常见的例子是 URLconf 文件中设置 Django View
from django.conf.urls.defaults import *from myproject.myapp.views import listviewurlpatterns = patterns('', url(r'^list/', listview))
这里的 listview 作为了一个包含了函数对象被直接使用,而不是一个包含了函数名字的字符串
另一个利用函数对象的地方时 model field 里的默认参数。
import datetimeclass DiaryEntry(models.Model): entry = models.TextField() date = models.DateField(default = datetime.date.today)
这里的 datetime.date.today后面没有() , 所以Django会在创建实例的时候才会调用函数而如果加上 (), 那么函数会在model定义的时候就调用,非我所想。
表达式和语句 expression & statement
python 代码由 表达式和语句构成,并由python解释器负责自行。
表达式是一个值,他的结果一定是一个python对象
lambda args:表达式
举个例子,对比下3个不同的处理方式:
这里有一个代表人物的复杂对象列表,希望按照姓氏排序
>>> list_of_people = [{'name':'ganiks', 'last_name':'liu'}, {'name':'henry', 'last_name':'ge'}]>>> list_of_people[{'last_name': 'liu', 'name': 'ganiks'}, {'last_name': 'ge', 'name': 'henry'}]>>> sorted(list_of_people, key = lambda person: person['last_name'])[{'last_name': 'ge', 'name': 'henry'}, {'last_name': 'liu', 'name': 'ganiks'}]
#key期望的是一个函数对象,而lambda返回的正好是一个匿名函数#这个例子简洁,目的明确sorted(list_of_people, key = lambda person: person.last_name)#这样也是等价的#这个方便重复使用函数def get_last_name(person): return person.last_namesorted(list_of_people, key = get_last_name)#不建议使用这种,我们希望lambda是一次性的函数定义#不过,这进一步阐述了Python函数的First-Class的特性get_last_name = lambda person: person.last_namesorted(list_of_people, key = get_last_name)
Django里面用到匿名函数的地方不多,但有个地方非常合适,即“认证装饰器” authentication decorator
,确认用户是否有足够权限访问页面;
将一个代表已登录用户的User对象传递给一个函数
@user_passes_test(lambda u: u.is_allowed_to_vote)def vote(request): """ Process a user's vote"""
这个例子中调用了一个函数user_passes_test
,接受了参数lambda u:u.is_allowed_to_vote
之后返回 另一个“装饰器”;也就是说装饰器是 user_passes_test(lambda u:u.is_allowed_to_vote)
无论是函数调用或者声明, *
都代表元组(或者列表)出现, **
代表字典出现。
函数调用里的 *
**
让参数容器列表、元组、字典更优雅
def check_web_server(host, port, path)
check_web_server('localhost', 8000, '/damin/')
host_info = ('www.python.org', 80, '/')
checck_web_server(host_info[0], host_info[1], host_info[2])
用*
让代码干净和优雅
check_web_server(*host_info)
host_info = {'host': 'www.python.org', 'port': 80, 'path': '/'}
check_web_server(**host_info)
函数签名里的 *
**
支持边长参数 varargs
在函数定义里使用变长参数时,参数的顺序是要求的;先是必须出现的参数,然后是由默认值的参数,最后才是变长参数
def check_web_server(host, port, path, *args, **args)
这个函数必须至少接受初始的三个参数,但是也能接受随后任何数目的参数或是关键字参数
还有一种全部由变长参数组成的所谓通用的Python方法签名
def f(*args, **kwargs):#正确调用f()f(a, b, c)f(a, b, foo=c, bar=d)
Django数据库API查询经常包含关键字参数,比如:
bob_stories = Story.objects.filter( title_contains = "bob", subtitle_contains = "bob", text_contains = "bob", byline_contains = "bob")#用变长参数字典来让参数独立bobargs = { 'title_contains': "bob", 'subtitle_contains': "bob", 'text_contains': "bob", 'byline_contain': "bob"}bob_stories = Story.objects.filter(**bobargs)#动态创建字典bobargs = dict((f + '__contains', 'bob') for f in ('title', 'subtitle', 'text', 'byline'))bob_stories = Story.objects.filter(**bobargs)
装饰器是一种让你能改变或者说“装饰” 函数行为的机制,能让函数执行一些和原本设计不同,或是在原有基础上额外的操作。
装饰器也可以说是对函数的一个包装,这些额外的任务包括写日志、计时、过滤
python 里的一个被包裹或者被装饰的函数(对象)通常会被重新赋值给原来的名字
@decodef foo(): pass
等价于
foo = deco(foo)
再举个例子记录下函数调用的发生:
>>> def log(func):... def wrappedFunc():... print "**** %s() called" % func.__name__... return func()... return wrappedFunc...>>> @log... def foo():... print "inside foo()"...>>> foo()**** foo() calledinside foo()
再看看之前的一个例子
将一个代表已登录用户的User对象传递给一个函数
@user_passes_test(lambda u: u.is_allowed_to_vote)def vote(request): """ Process a user's vote"""
这个例子中调用了一个函数user_passes_test
,接受了参数lambda u:u.is_allowed_to_vote
之后返回 另一个“装饰器”;也就是说装饰器是 user_passes_test(lambda u:u.is_allowed_to_vote)
它的逻辑是这样的:
@decomaker(deco_args)def foo(): pass
等价于
foo = decomaker(deco_args)(foo)
再比如应用多个装饰器:
@deco1(deco_args@)@deco2def foo(): pass
为什么要用装饰器呢?
本质就是包裹函数,接受对象,修改并重新赋值给原来的变量;
OOP的主要目标是在代码和显示问题之间提供一个合乎逻辑的映射关系,并且鼓励代码的重用和共享。
class AddressBookEntry(object): version = 0.1 def __init__(self, name, phone): self.name = name self.phone = phone def update_phone(self, phone): self.phone = phone
静态成
员属于整个类的变了,可以再所有的实例之间共享self对象
john = AddressBookEntry('Jone Doe', '400999999')jane = AddressBookEntry('Jane Dey', '300293202')>>> john.phone'400999999'>>> john.tattoo = 'Mom'
python中实例化不需要像其他语言一样new对象,而是可以直接调用函数一样即可
python用的是初始化程序initializer而不是构造函数 constructor,所以名字也是__init__
在实例化一个对象的时候,不用传入self对象,python会自动为你传入self对象
PS: python还支持直接创造没有在类定义中声明的对象,比如上面例子中的tattoo
class EmployeeAddressBookEntry(AddressBookEntry): def __init(self, name, phone, id, social): AddressBookEntry.__init__(self, name, phone) self.empid = id self.ssn = social
嵌套类的概念类似于创建装饰器的“嵌套函数”,即在类的内部定义类
class MyClass(object): class InnerClass: pass
form django.db import modelsfrom django.contrib import adminclass BlogPost(models.Model): title = models.CharField(max_length = 150) body = models.TextField() timestamp = models.DateTimeField()class Meta: ordering = ('-timestamp',)
Django的数据model是从Django内置类 django.db.models.Model 继承而来的子类
re.search 返回一个匹配对象Match,随后可以用这个对象的 group 或者 groups
方法获取匹配的模式;匹配失败时,返回的是None
额,这里用“匹配”有点不准确,确切的说是“搜索”,而“匹配”指的是整个字符串都要符合模式的描述
>>> import re>>> m = re.search(r'foo', 'seafood')>>> print m<_sre.SRE_Match object at 0x00DAE4B8>>>> m.group<built-in method group of _sre.SRE_Match object at 0x00DAE4B8>>>> m.group()'foo'>>> m = re.search(r'bar', 'seafood')>>> print mNone>>>>>>>>> import re>>> m = re.match(r'foo', 'seafood')>>> if m is not None: print m.group()...>>> print mNone>>> if m is not None: print m.groups()...>>> print mNone>>> m = re.search(r'foo', 'seafood')>>> if m is not None: print m.group()...foo>>> if m is not None: print m.groups()...()>>> if m is not None: print m.group()...foo
import randomprint random.choice(range(10))from random import choiceprint choice(range(10))
python有导入模块和加载模块之分,一个模块可以被导入N次,但是只会被加载一次,无需担心额外消耗内存的问题。
package是Python在文件系统上发布一组模块的一种方式,通过 __init__.py
实现
Phone/ __init__.py util.py Voicedata/ __init__.py posts.py Isdn.py Fax __init__.py G3.py Mobile __init__.py Anolog.py Digital.py
__init.__.py
告诉Python解释器这些目录下的文件应该被当做是一个子package而不是普通文件,一般它们都是空文件,当然也可以做一些初始化的工作。
import Phone.Mobile.AnalogPhone.Mobile.Anolog.dial()import Phone.Mobile.Analog as pmapma.dial()
在Python中跟一般不这么说,而是说 对象时可变或者不可变 mutable or immutable
对象有 类型,标示符,值 三个属性, 如果值 是可变的,那么这个对象就是可变的;
前面语法其实已经介绍过了,标量scalar类型(整数浮点数复数)、str、unicode字符串、元组是不可变的;其他的列表、字典、类、类实例都是可变的。
可变性是Python中重要的概念,这也解释了为什么Python要提供两种列表, list 和 tuple
如果你调用的函数有任何修改一个可变对象的行为的话,通常它都是直接修改的,即直接修改数据结构而不是返回一个拷贝(返回None)
比如 list.sort, list.reverse, list.extend, dict.update都是直接修改
深拷贝和浅拷贝 deep copy & shallow copy
>>> from copy import deepcopy>>> mylist2 = deepcopy(mylist)>>> mylist2[1, 'a', ['foo', 'bar']]>>> mylist2[0] = 2>>> mylist2[2][0] = 'biz'>>> mylist2[2, 'a', ['biz', 'bar']]>>> mylist[1, 'a', ['foo', 'bar']]>>> mylist2 = list(mylist)>>> mylist2[0] = 2>>> mylist2[2][0] = 'biz'>>> mylist[1, 'a', ['biz', 'bar']]>>> mylist2[2, 'a', ['biz', 'bar']]
上面的例子中分别是一个深拷贝和浅拷贝的例子,先看看浅拷贝:
mylist中前两个对象时整数和字符串,所以mylist2会得到2个全新的整数和字符串对象,所以1=>2
但是mylist的第三个对象时列表,列表时可变的,所以mylist2得到的只是一个引用,所以
‘foo'=>'biz'影响到了mylist本身
而深拷贝就不会了, 1=>2 'foo'=>'biz' 都不会影响mylist
深拷贝通常是地柜的(如果循环引用会有问题),而且不是所有的对象都是可以深拷贝的。
虽然Python是OOP的语言,但是没有显式的构造函数的概念,没有 new 关键字,没有
真的实例化你的类。
python会为你创建实例并调用初始化程序,在你的对象创造出来之后,Python将它返回给你之前调用的第一个方法__init__
>>> from time import ctime>>> class MyClass(object):... def __init__(self, date):... print "instance created at: ", date...>>> m = MyClass(ctime())instance created at: Sat Sep 27 10:31:22 2014>>>
另外python也没有析构函数来销毁对象,只要让它离开作用域就行了,会被自动垃圾回收。
不过,你可以在 python对象中定义一个 __del__
方法来当做析构函数,可以用 del my_object
来显式的销毁对象。
动态实例属性
Python的另一个重要的特性是动态实例属性
dynamic instance attribute
实例的属性可以动态分配,
即使在类定义已经完成甚至是已经创建里实例,还是可以给你的实例添加一个之前没有提到过的属性
创建文档字符串(docstring)
C:/Documents and Settings/ganiks.liu/Desktop>vim foo.py"""foo.py --sample module demostrating documentation strings """class Foo(object): """ Foo() - empty class ... tobe developed """def bar(x): """bar(x) - function docstring for bart, prints out its arg 'x'""" print xC:/Documents and Settings/ganiks.liu/Desktop>pythonPython 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] on win32Type "help", "copyright", "credits" or "license" for more information.>>> import foo>>> foo.__doc__'foo.py --sample module demostrating documentation strings '>>> foo.Foo.__doc__' Foo() - empty class ... tobe developed '>>> foo.bar.__doc__"bar(x) - function docstring for bart, prints out its arg 'x'">>> help(foo)Help on module foo:NAME foo - foo.py --sample module demostrating documentation stringsFILE c:/documents and settings/ganiks.liu/desktop/foo.pyCLASSES __builtin__.object Foo class Foo(__builtin__.object) | Foo() - empty class ... tobe developed | | Data descriptors defined here: | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined)FUNCTIONS bar(x) bar(x) - function docstring for bart, prints out its arg 'x'
新闻热点
疑难解答