设为首页 收藏本站
查看: 1802|回复: 0

[经验分享] 跟我一起Django

[复制链接]

尚未签到

发表于 2015-4-19 08:00:00 | 显示全部楼层 |阅读模式
  目录:


  • Python技术就是Django技术  

  • Python交互解释器python&iPython  

  • Python语法基础,注释、变量和赋值,符号  

  • Python标准类型,布尔,数字,字符串str,列表list,元组tuple,字典dict  

  • Python流程控制  

  • Python异常处理  

  • 文件  

  • 函数  

  • 面向对象编程  

  • 正则表达式  

  • 常见错误  

  • 代码风格  

  • 总结
  参照内容:经典Django教程《Python+Django+Web开发指南》
  重点概念:
  

交互解释器  
tab还是空格
  
对象的布尔值
  
经典除法 真正除法
  
内置数字工厂
  
序列
  
列表,字符串,元组
  
列表推导式
  
生成器表达式
  
不可变
  
字符串指示符
  
内置序列函数
  
表达式 语句
  
匿名函数 lambda
  
垃圾自动回收
  
动态实例属性
  

3.1 Python技术就是Django技术
  Django提供了一个高级的框架,用它只需要很少代码就可以完成一个Web应用。
  Django使用Python写成的,Python是一门OOP的开发语言,同时兼具系统语言(C、C++、Java)的强大和脚本语言(Ruby和VB)的灵活迅速。


本节主要总结Django工程师一定要知道的Python概念,而不是一份通用的Python教程。

  http://www.iyunv.com/ganiks

3.2 入门:Python交互解释器
  Python Shell中,不用去创建和保存一个源文件,就可以直接把代码拿来测试。
  

>>> print 'Hello world!'  
Hello World!
  

  来看一个复杂的例子:
  

ganiks.liu@MAMIS-GAIKS-LIU /E/mysite (master)  
$ python
  
Python 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] on win32
  
Type "help", "copyright", "credits" or "license" for more information.
  
>>> for word in ['capitalize', 'these', 'words']:
  
... print word.upper()
  File "", line 2
  print word.upper()
  ^
  
IndentationError: expected an indented block
  
>>> for word in ['capitalize', 'these', 'words']:
  
...     print word.upper()
  
...
  
CAPITALIZE
  
THESE
  
WORDS
  
>>> for i in rang(0,5):
  
...     print i
  
...
  
Traceback (most recent call last):
  File "", line 1, in
  
NameError: name 'rang' is not defined
  
>>> for i in range(0,5):
  
...     print i
  
...
  
0
  
1
  
2
  
3
  
4
  
>>>
  


python语法中重要的一个方面就是没有区分代码库的花括号{ }, 而是用对齐来替代


更高级的交互解释器iPython
  iPython的能力完全是另一个数量级上的解释器。它提供了系统shell访问、命令行技术、自动对齐、命令行历史等许多特性。

在解释器里使用Django


要是能在Python的解释器中调试Django应用是不是很酷?



  • 假如你只是按照常规启动解释器并且试着导入Django模块,你只能得到一个  DJANGO_SETTINGS_MODULE没有设置的错误。为了方便起见,Django提供了一个manage.py
      shell命令,能进行一些必要的环境设置来避免
      

  • 如果安装了 iPython, manage.py shell 会默认使用它。  

  • 如果你安装了iPython,又希望能使用标准Python解释器的话,可以运行manage.py  shell plain

3.3 Python基础


  • 注释 —— #  

  •   变量和赋值 —— 除非你想解释器询问更多信息,否则你不可能百分百确定变量在任何给定的时刻是什么类型的对象
      

    $ python  
    Python 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] on win32
      
    Type "help", "copyright", "credits" or "license" for more information.
      
    >>> foo = 'bar'
      
    >>> foo
      
    'bar'
      
    >>> type(foo)
      

      
    >>> foo = 1
      
    >>> type(foo)
      

      
    >>>

  • 运算符  

  • 避免使用的符号  

  • 结尾的 ;  

  • $  

  •   条件语句的()


Python的作者:只有干净和容易阅读的代码才能避免混乱


3.4 Python标准类型


  • 标量(scalar)  

  • 文字量(literal) 比如数字/字符串  

  • 多个Python对象组织在一起的容器、数据结构
3.4.1 对象的布尔值
  所有的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
  
>>>
  

3.4.2 数字


  • int 带符号整数 **python只有一种整数类型**  

  • float 双精度浮点数  

  • complex 复数
  

>>> type(3.75)  

  
>>> type(0377)
  

  
>>> type(0xE8C6)
  

  
>>> type(2+2j)
  

  

3.4.2.1 数字运算符

+ - *  

/ floor division 经典除法(整数相除结果取整,浮点相除结果取浮点)  

// true division 真正的除法 (统统取整数结果)  

% 取模  

** 指数运算  

& | ~ ^ >> >> 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'
  
>>>
  

3.4.3 序列和迭代
  序列类型类似其他语言中的数组,不同的是:


  • 数组是定长的,而序列长度可以伸缩  

  • 数组有相似的对象组合,可以包含不同类型的对象
  常见的序列有:


  • 列表 list [1, 2, 3] [123, 'foo', 3.14]  

  • 字符串 string 'python' '\n' '%s is number %d'  

  • 元组 tuple (45, 2.71) () ('need a comma even with just 1 item',)
  像数组一样, 序列可以直接索引:
  

>>> 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'
  

3.4.4 列表
  

>>> book=['python', 'develop', 8]  
>>> book.append(2008)
  
>>> book.insert(1, 'web')
  
>>> book
  
['python', 'web', 'develop', 8, 2008]
  
>>> book[:3]
  
['python', 'web', 'develop']
  
>>> 'django' in book
  
False
  
>>> 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']
  

列表推导式[ ] and 生成器表达式( )
  

>>> 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
  

  

  如果你的输入序列很大,最好用生成器表达式,节省内存


3.4.5 字符串

  字符串不能修改,大小也不能改变
  任何没有一个能修改现有的对象的方法,只是返回一个修改了的拷贝
  到目前为止,已经有超过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'
  
>>>
  

字符串指示符 u r
  

>>> mystr = u'This is Unicode'  
>>> mystr
  
u'This is Unicode'
  
>>> print mystr
  
This is Unicode
  

  
>>> filename = 'C:\temp\newfolder'
  
>>> filename
  
'C:\temp\newfolder'
  
>>> print filename
  
C:      emp
  
ewfolder
  
>>> filename = r'C:\temp\newfolder'
  
>>> print filename
  
C:\temp\newfolder
  

  
#为了保持一致,所有的正则表达式都要用raw指示符
  
>>> regex = "\w+@\w+\.\w+"
  
>>> print regex
  
\w+@\w+\.\w+
  
>>> regex = r"\w+@\w+\.\w+"
  
>>> print regex
  
\w+@\w+\.\w+
  

Unicode指示符
  通常Python字符串都只含有很少字符,不足以显示更多的非英文字符。而Unicode是新型的字符集,拥有大量的编码方式,不存在这个显示。
  

>>> str = "中国"  
>>> str
  
'\xd6\xd0\xb9\xfa'
  
>>> str = u"中国"
  
>>> str
  
u'\u4e2d\u56fd'
  
>>> str = r"中国"
  
>>> str
  
'\xd6\xd0\xb9\xfa'
  
>>> print str
  
中国
  
>>> str = u"中国"
  
>>> print str
  
中国
  
>>> str = "中国"
  
>>> print str
  
中国
  

字符串格式化操作符 adn 三引号操作符
  

>>> s = 'Django is cool'  
>>> '%s is number %d' % (s[:6], 1)
  
'Django is number 1'
  
>>> hi = '''hi
  
... there'''
  
>>> hi
  
'hi\nthere'
  
>>> print hi
  
hi
  
there
  

  展示一个高级应用的实例
  

>>> xml = '''  
...
  
...
  
...   
  
...        %s
  
...   
  
...
  
... '''
  
>>> VERSION = 1.2
  
>>> payload = 'super top-secret info'
  
>>> print (xml %(VERSION, payload))
  

  

  

  
  super top-secret info
  
  

  

3.4.6 元组
  表明上元组和列表只是用什么括号() []的区别,深层次的区别则要说道Python的对象模型。

  列表允许改变值,元组不可以!(像字符串)所以元组没有方法。

  但是元组也不单单是一个只读列表,元组的主要作用是作为参数传递给函数调用,或是从函数调用那里获取参数时, 保护其内容不被外部接口修改。
  所以元组在前台的用武之地不大,但是在后台却很频繁使用,例如Django的配置文件中的admin选项、URLconf规则、settings.py配置。

  !!! 单个元素的元组要求在最后“必须”跟一个逗号,元组是逗号决定的,而不是小括号。

  

>>> a = ("one", "two")  
>>> a
  
('one', 'two')
  
>>> type(a)
  

  
>>> a[0]
  
'one'
  
>>> a = ('just-one')
  
>>> a
  
'just-one'
  
>>> type(a)
  

  
>>> c = ('just-one',)
  
>>> c
  
('just-one',)
  
>>> type(c)
  

  
>>> d = "just-one",
  
>>> d
  
('just-one',)
  
>>> type(d)
  

  

内置序列函数和工厂函数


  • str  

  • list  

  • tuple  

  • len  

  • max  

  • min  

  • range(1,10)  

  • sorted  

  • sum  

  • any  

  • zip
  

>>> a=("one","two")  
>>> type(a)
  

  
>>> a
  
('one', 'two')
  
>>> len(a)
  
2
  
>>> max(a)
  
'two'
  
>>> sorted(a)
  
['one', 'two']
  
>>> sum(a)
  
Traceback (most recent call last):
  File "", line 1, in
  
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 "", line 1, in
  
TypeError: unsupported operand type(s) for +: 'int' and 'str'
  

3.4.7 字典
  字典是Python中唯一的映射类型,可变的,无序的,大小可变的键值映射;别名散列表(hashes) 关联数组
  虽然语法跟序列相似,但是用键而不是下标来访问元素;而且定义的话使用的花括号{ }

字典的操作、方法和映射函数


  • keys  

  • values  

  • items  

  • get  

  • pop  

  • update
  

>>> book = {'title':'Python Web Dev', 'year':2008}  
>>> book
  
{'year': 2008, 'title': 'Python Web Dev'}
  
>>> type(book)
  

  
>>> 'year' in book
  
True
  
>>> book.get('pub')
  
>>> book.get('pub', 'N/A')
  
'N/A'
  
>>> book['pub']
  
Traceback (most recent call last):
  File "", line 1, in
  
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 "", line 2
  print key, ':', book[key]
  ^
  
IndentationError: expected an indented block
  
>>> for key in book:
  
...     print key, ':', book[key]
  
...
  
year : 2008
  
pub : Addision Wesley
  
title : 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是应用的最频繁的数据类型

3.5. Python流程控制

3.5.1 判断if elif else
  

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"
  

3.5.2 循环 常用 for
  

>>> i = 0  
>>> while i < 5:
  
...     print i
  
...     i += 1
  
...
  
0
  
1
  
2
  
3
  
4
  

  更常用的是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 "", line 1, in
  
TypeError: 'int' object is not iterable
  
>>> for i, value in data:
  
...     print value
  
...
  
Traceback (most recent call last):
  File "", line 1, in
  
TypeError: 'int' object is not iterable
  
>>> for value in data:
  
...     print value
  
...
  
123
  
abc
  
3.14
  

>>> data = (123, 'abc', 3.14)  
>>> for i, value in enumerate(data):
  
...     print i, value
  
...
  
0 123
  
1 abc
  
2 3.14
  
>>>
  

在Django的Model中使用 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界面中显示的确实是文字标签。
  这样利用数据库存储的效率高,而且???当出现字符无法按照预想顺序排序的时候也比较方便。

3.6. Python异常处理
  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", e
  
except ArithmeticError, e:
  print "ERROR: some math error", e
  
except Exceptioin, e:
  print "ERROR: invalid data", e
  

finally子句
  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()
  

用raise抛出异常
  

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(): ...")
  

常见异常类型


  • AssertionError  

  • AttributeError  

  • IOError  

  • ImportError  

  • IndentationError  

  • IndexError  

  • KeyError  

  • Keyboardinterrupt  

  • NameError  

  • SyntaxError  

  • TypeError  

  • UnboundLocalError  

  • ValueError
  more refert to : https://docs.python.org/2.7/library/exceptions.html#module-exceptions

3.7. 文件
  

>>> f = open('test.txt', 'w')  
>>> f.write('foo\n')
  
>>> f.write('bar\n')
  
>>> f.close()
  
>>> dir
  

  
>>> f = open('test.txt', 'r')
  
>>> for line in f:
  
...     print line.rstrip()
  
...
  
foo
  
bar
  

  
>>> f = open('test.txt', 'r')
  
>>> for line in f:
  
...     print line
  
...
  
foo
  

  
bar
  

  

  除了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'
  

3.8. 函数(重点)


  • 声明和调用函数  

  • (函数调用里的)关键字参数  

  • (函数签名里的)默认参数  

  • 函数式first-class的对象  

  • 匿名函数和lambda  

  • (函数调用里的)参数容器  

  • (函数签名里的)变长参数  

  • 装饰器
3.8.1 声明和调用函数
  

>>> 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 Permanently
  
HTTP 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 =  OK
  
HTTP 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; pat
  
h=/
  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
  
>>>
  

3.8.2 (函数调用里的)关键字参数
  调用的时候,我们需要记得函数定义中的参数顺序:host, port, path
  那如果没有记得呢,可以用关键字参数,也是ok的
  

>>> check_web_server(path='/', port=80, host='www.baidu.com')  

3.8.3 (函数签名里的)默认参数
  定义函数的时候,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]
  

3.8.4 函数是First-Class的对象

  对象引用
  在Python里面,你可把函数和方法当做和其他对象一样的使用

  只有当我们要调用函数的时候才会加上小括号(), 在把它当做变量或者对象传来传去的时候,只需要用函数的名字就好。
  这将引用bar和调用bar()区分开来
  

>>> def bar():  
...     print "bar"
  
...
  
>>> bar()
  
bar
  
>>> baz = bar
  
>>> baz()
  
bar
  
>>>
  
>>>
  
>>> function_list = [bar, baz]
  
>>> for function in function_list:
  
...     function()
  
...
  
bar
  
bar
  

Django里的First-Class函数
  常见的例子是 URLconf 文件中设置 Django View
  

from django.conf.urls.defaults import *  
from myproject.myapp.views import listview
  

  
urlpatterns = patterns('',
  url(r'^list/', listview)
  
)
  

  这里的 listview 作为了一个包含了函数对象被直接使用,而不是一个包含了函数名字的字符串
  另一个利用函数对象的地方时 model field 里的默认参数。
  

import datetime  

  
class DiaryEntry(models.Model):
  entry = models.TextField()
  date = models.DateField(default = datetime.date.today)
  

  这里的 datetime.date.today后面没有() , 所以Django会在创建实例的时候才会调用函数而如果加上 (), 那么函数会在model定义的时候就调用,非我所想。
  http://www.iyunv.com/ganiks

3.8.5 匿名函数和lambda

  表达式和语句 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_name
  
sorted(list_of_people, key = get_last_name)
  

  
#不建议使用这种,我们希望lambda是一次性的函数定义
  
#不过,这进一步阐述了Python函数的First-Class的特性
  
get_last_name = lambda person: person.last_name
  
sorted(list_of_people, key = get_last_name)
  

Django里面的匿名lambda函数
  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)

*args && **kwargs
  无论是函数调用或者声明, *都代表元组(或者列表)出现, **代表字典出现。

3.8.6 (函数调用里的)参数容器
  函数调用里的 * ** 让参数容器列表、元组、字典更优雅
  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)

3.8.7 (函数签名里的)变长参数
  函数签名里的 * ** 支持边长参数 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 QuerySets里的 **kwargs: 动态创建ORM查询
  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)
  

3.8.8 装饰器
  装饰器是一种让你能改变或者说“装饰” 函数行为的机制,能让函数执行一些和原本设计不同,或是在原有基础上额外的操作。
  装饰器也可以说是对函数的一个包装,这些额外的任务包括写日志、计时、过滤
  python 里的一个被包裹或者被装饰的函数(对象)通常会被重新赋值给原来的名字
  

@deco  
def 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() called
  
inside 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@)  
@deco2
  
def foo():
  pass
  

  为什么要用装饰器呢?
  本质就是包裹函数,接受对象,修改并重新赋值给原来的变量;
不同的是装饰器可以让你用一个简单的 at 符号来完成这一切动作
3.9. 面向对象编程
  OOP的主要目标是在代码和显示问题之间提供一个合乎逻辑的映射关系,并且鼓励代码的重用和共享。

3.9.1 类的定义
  

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
  


  • version这样的静态成员属于整个类的变了,可以再所有的实例之间共享  

  • 方法的定义和函数的一点区别,每个方法都必须带上一个额外的self对象  

  • python没有构造函数和析构函数,也没有 new free关键字
3.9.3 实例化
  

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

3.9.3 继承
  

class EmployeeAddressBookEntry(AddressBookEntry):
  def __init(self, name, phone,>  AddressBookEntry.__init__(self, name, phone)

  self.empid =>  self.ssn = social
  

3.9.4 嵌套类
  嵌套类的概念类似于创建装饰器的“嵌套函数”,即在类的内部定义类
  

class MyClass(object):  class InnerClass:
  pass
  

Django中的嵌套类应用实例--Django Model
  

form django.db import models  
from django.contrib import admin
  

  
class 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 继承而来的子类


3.10. 正则表达式
  re.search 返回一个匹配对象Match,随后可以用这个对象的 group 或者 groups
  方法获取匹配的模式;匹配失败时,返回的是None
  额,这里用“匹配”有点不准确,确切的说是“搜索”,而“匹配”指的是整个字符串都要符合模式的描述
  

>>> import re  
>>> m = re.search(r'foo', 'seafood')
  
>>> print m
  

  
>>> m.group
  

  
>>> m.group()
  
'foo'
  
>>> m = re.search(r'bar', 'seafood')
  
>>> print m
  
None
  
>>>
  
>>>
  
>>> import re
  
>>> m = re.match(r'foo', 'seafood')
  
>>> if m is not None: print m.group()
  
...
  
>>> print m
  
None
  
>>> if m is not None: print m.groups()
  
...
  
>>> print m
  
None
  
>>> 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
  

3.11. 常见错误

3.11.1 单元素的元组


  • ()  

  • (123, 'xyz', 3.14)  

  • (1)  

  • (1,)
3.11.2 模块
  

import random  
print random.choice(range(10))
  

  
from random import choice
  
print choice(range(10))
  


  • 第一种方法将模块的名字设置为一个隐含的名字空间里的全局变量,这样可以像访问全局属性一样访问choice函数  

  • 第二种方法直接把choice引入到全局名字控件,因此不再需要把这个属性当成是模块的成员,实际上我们也只拥有这个属性而已  

  • 但是并不是说,第二种方式只引入了一个函数,而没有导入整个模块,其实是导入了整个模块的!!!所以没有性能的差异
3.11.3 能否重复导入模块??
  python有导入模块和加载模块之分,一个模块可以被导入N次,但是只会被加载一次,无需担心额外消耗内存的问题。

3.11.4 Package
  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.Analog  
Phone.Mobile.Anolog.dial()
  

  
import Phone.Mobile.Analog as pma
  
pma.dial()
  

3.11.5 可改变性,到底Python是传引用 还是 传值?
  在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
  深拷贝通常是地柜的(如果循环引用会有问题),而且不是所有的对象都是可以深拷贝的。

3.11.6 构造函数 vs 初始化程序
  虽然Python是OOP的语言,但是没有显式的构造函数的概念,没有 new 关键字,没有
  真的实例化你的类。
  python会为你创建实例并调用初始化程序,在你的对象创造出来之后,Python将它返回给你之前调用的第一个方法__init__
  

>>> from time import ctime
  
>>>>  
...     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
  实例的属性可以动态分配,
  即使在类定义已经完成甚至是已经创建里实例,还是可以给你的实例添加一个之前没有提到过的属性

3.12. 代码风格


  • 四格对齐  

  • 使用空格而非Tab  

  • 不要像标题一样把一组代码放在同一行里  

  •   创建文档字符串(docstring)
      

    C:\Documents and Settings\ganiks.liu\Desktop>vim foo.py  
    """foo.py --sample module demostrating documentation strings """
      
    class Foo(object):

      """ Foo() - empty>  
    def bar(x):
      """bar(x) - function docstring for bart, prints out its arg 'x'"""
      print x
      
    C:\Documents and Settings\ganiks.liu\Desktop>python
      
    Python 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] on win32
      
    Type "help", "copyright", "credits" or "license" for more information.
      
    >>> import foo
      
    >>> foo.__doc__
      
    'foo.py --sample module demostrating documentation strings '
      
    >>> foo.Foo.__doc__

      
    ' Foo() - empty>  
    >>> 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 strings
      
    FILE
      c:\documents and settings\ganiks.liu\desktop\foo.py
      
    CLASSES
      __builtin__.object
      Foo
      class Foo(__builtin__.object)

      |  Foo() - empty>  |
      |  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'

3.13. 总结

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-58555-1-1.html 上篇帖子: Python天天美味(总) 下篇帖子: python threading模块
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表