`
friendsys
  • 浏览: 338827 次
  • 性别: Icon_minigender_1
  • 来自: 福州
社区版块
存档分类
最新评论

Learning.Python.3rd.Edition 笔记[14:17]

阅读更多
Chapter 15
Function Basics  函数基础

常用的function操作
Statement Examples
Calls myfunc("spam", "eggs", meat=ham)
def, return, yield def adder(a, b=1, *c):
return a+b+c[0]
global def changer( ):
global x; x = 'new'
lambda Funcs = [lambda x: x**2, lambda x: x*3]


function的作用
1:最大限度的代码重用和最小限度的冗余
2:程序(流程)上的分解

def的语法格式
def <name>(arg1, arg2,... argN):
    <statements>
    return <value>

return是可选的,如果没有,将会返回None,不过通常捕获该类型

运行时,通过def重新定义函数,来实现类似多态的方法,在方法内定义方法
if test:
def func( ): # Define func this way
...
else:
def func( ): # Or else this way
...
...
func( ) # Call the version selected and built

与JavaScript类似.function也是一种单独的对象,在与变量赋值时,不需要(), 被复制后的对象只要()就可以进行
方法的调用

其他介绍的东西也比较简单,不做介绍..凑字数问题省略


Chapter 16
Scopes and Arguments
作用域与参数

对变量域的使用,有不少需要注意的地方

X = 99
def func( ):
    X = 88

module中定义了一个global作用域,functions中定义了一个local作用域

LEGB规则: 用于定义变量搜索的作用域顺序
1:local(L) scope     函数局部域   
2:enclosing (E)  
3:global (G) scope   module全局域
4:built-in (B) scope Python内置域

详细介绍的例子
# Global scope
X = 99 # X and func assigned in module: global
def func(Y): # Y and Z assigned in function: locals
    # Local scope
    Z = X + Y # X is a global
    return Z
func(1) # func in module: result=100

对全局域的修改,与Java不同,更类似是参数的传递,对简单类型,如String,int等,对该类型的值修改将无效,
而对于list等对象类型,修改将会被保留,同样不能直接指向其他的对象.

如果需要在函数中修改global作用域的参数,需要在function内使用global声明一个全局函数,表示该变量为
global中的变量

X = 88 # Global X
def func( ):
    global X
    X = 99 # Global X: outside def
func( )
print X # Prints 99


注意由于作用域的存在,优先的作用域内定义的变量,有可能会覆盖掉外部的函数,如内嵌函数,所有尤其注意
变量名规范

减少global变量
全局变量会导致程序难以调试,所以不推荐使用,可以使用传递参数和返回值代替

减少跨文件修改
# first.py
X = 99
# second.py
import first
first.X = 88

如同Java中的一样, 使用get和set方法替换

其他访问与修改global变量的方法
var = 99

def local( ):
    var = 0
def glob1( ):
    global var   //最简单的方式
    var += 1

def glob2( ):
    var = 0
    import thismod  // 使用模块修改 Import myself
    thismod.var += 1

def glob3( ):
    var = 0
    import sys //字典方式 Import system table 使用模块修改
    glob = sys.modules['thismod']
    glob.var += 1


动态的返回function
def f1( ):
    x = 88
    def f2( ):
        print x
    return f2
action = f1( ) # Make, return function
action( ) # Call it now: prints 88

上述方法调用,可以产生类似closure的应用,通过一个factory functions生成一个独立的function对象,然后
返回

独立的关键在于传入factory functions的值,将会被保留在生成的function之中

def maker(N):
    def action(X):
        return X ** N
    return action

使用lambda 代替在function内定义的简单def函数

def func( ):
    x = 4
    action = (lambda n: x ** n) # x remembered from enclosing def
    return action
x = func( )
print x(2) # Prints 16, 4 ** 2

如果徐需要给lambda或者内置函数设置对应的默认值,可以使用

x = 4
action = (lambda n, x=x: x ** n)   //注意x=x的使用

同理在内置函数上
def f2(x=x):
    print x

可以使用list保存生成的function对象
def makeActions( ):
    acts = []
    for i in range(5): # Tries to remember each i
         acts.append(lambda x: i ** x) # All remember same last i!
    return acts
   
acts = makeActions( )
acts[0](2) //调用

同样也可以使用默认值的形式
acts.append(lambda x, i=i: i ** x)

不建议使用多层的嵌套def
flat is better than nested

对于Python参数传递简单的理解:
1: 对于不可变对象为传值
2: 对于可变对象为传递引用

在对可变参数的修改时,有可能导致发生意想不到的问题,所以不推荐使用,Python支持
同时return多个参数,可以使用该方法进行代替(类似返回tuple)

def multiple(x, y):
    x = 2 # Changes local names only
    y = [3, 4]
    return x, y # Return new values in a tuple

X = 1
L = [1, 2]
X, L = multiple(X, L) # Assign results to caller's names
X, L

Python下参数传递的方式:
1:传统的从左到右的完整参数传递
2:使用默认值,需要注意顺序
3:使用key=value的方式传递参数
4:使用集合捕获参数(包括tuple和dict)--多余的参数

大概格式如下

func(value) Caller Normal argument: matched by position
func(name=value) Caller Keyword argument: matched by name
func(*name) Caller Pass all objects in name as individual positional arguments
func(**name) Caller Pass all key/value pairs in name as individual keyword arguments
def func(name) Function Normal argument: matches any by position or name
def func(name=value) Function Default argument value, if not passed in the call
def func(*name) Function Matches and collects remaining positional arguments (in a tuple)
def func(**name) Function Matches and collects remaining keyword arguments (in a dictionary)

*用于捕获任意数量参数,保存为tuple
**用于捕获任意数量key=value形式的参数,保存为dict
两者可以配合使用,不过注意需要确认*必须在**之前

同样,可以将tuple和dict作为参数进行传入,从而调用*与**的函数

也可以在参数中使用*(a,) 和 **{'c'=2} 进行*与**的调用

本章主要介绍了Python function中的作用域scopes和参数arguments

凑字数问题省略


Chapter 17
Advanced Function Topics
高级function

匿名函数:lambda

lambda Expressions 表达式
lambda argument1, argument2,... argumentN : expression using arguments
如:
kc=lambda k,c:k+c
print kc('k','c')

lambda设计用于小型的function,如:可以保存在对象属性中,也可以保存在list或dict中,而def用于较大的任务

同样也可以给参数设置默认值,使用()可以让代码更易阅读一些
kc=(lambda k,c=3:k+c)

lambda也常用于代替嵌套function的 def返回

在class调用本身方法时,可以使用self.方法名()进行调用

内置的apply 函数 ---- 用于将function与参数分开,然后合并执行
apply(action, args)  //其中args为元组

apply(echo, pargs, kargs)  // kargs 用于保存{}dict,表示key=value的形式传递参数,注意key必须为str

kc=lambda k,c:k+c
print apply(kc,(),{'k':1,'c':3})  //使用时,注意第二个参数是必须的

方法调用时,可以使用*和**明确指定参数区域
echo(0, *pargs, **kargs)  # Normal, *tuple, **dictionary

kc=lambda *d,**c:d[0]+c['d']
d=(1,23,2,3)
c={'d':3}
print kc(*d,**c)

使用内置的map方法,重复调用一个函数..

counters = [1, 2, 3, 4]
def inc(x): return x + 10
map(inc, counters)
这样将会执行对应的方法,传入list中参数,并返回一个List

可以使用Lambda进行替换
map((lambda x: x + 3), counters)

可以使用三个参数的进行两个参数形式的调用
pow(3, 4)
//81
map(pow, [1, 2, 3], [2, 3, 4]) # 1**2, 2**3, 3**4

同理如果参数更多,可以使用同样的方法进行调用
kc=lambda a,b,c: a*b*c
print map(kc,(1,2,3),(4,5,6),(7,8,9))

filter and reduce ---其他的函数应用  //3.0中将被移除

filter顾名思义,进行过滤
kc=lambda a: a>5
print filter(kc,range(0,10))   //如果使用map,将会返回判断结果,而使用filter将返回符合条件的结果

reduce将会将计算结果作为参数,与后置参数进行递归调用
reduce((lambda x, y: x + y), [1, 2, 3, 4])

可以使用链表推导式代替上述function
List comprehensions

在lambda中并不能使用if,链表推导式可以
[x for x in range(5) if x % 2 == 0]

链表表达式的格式如下
[ expression for target1 in sequence1 [if condition]
             for target2 in sequence2 [if condition] ...
             for targetN in sequenceN [if condition] ]
例子如:
res = [x + y for x in [0, 1, 2] for y in [100, 200, 300]]

可以从多个list中获取值
较复杂的例子
[(x, y) for x in range(5) if x % 2 == 0 for y in range(5) if y % 2 == 1]

在性能方面,map的速度大概是传统循环的两倍,list comprehension比map稍微快一些


yield 相关的生成器Generator

简单的例子
def ff():
    for x in range(1,10):
        yield x

x=ff() //注意这一步是必须的,需要创建一个function对象的实例
print x.next()
print x.next()
print x.next()
print x.next()

也可以使用list推导式达到上述的效果
G = (x ** 2 for x in range(4))
G.next()
注意 多次next()后,有可能因为越界,而抛出异常

可以使用多层的for 循环进行自动获取所有的值
for num in (x ** 2 for x in range(4)):
    print '%s, %s' % (num, num / 2.0)

可以使用sum,sorted,等方法直接对Generator进行操作

生成器的主要在于,每次只产生一个对象,能够节约内存的空间

注意生成器和List推导式 明显的区别在于()和[]

可以使用import time 模块,简单的判断代码执行的时间,提供运行效率的参考

函数设计规范
1:使用arguments输入和使用return返回
2:只有在必须的时候使用全局变量
3:除非调用者需要,否则不要修改可变参数arguments
4:每个函数都必须有一个单一的用途
5:函数应该尽可能的短
6:应该避免直接修改其他模块的变量

对python中参数的默认值进行修改后,将会影响后续function调用,可以通过验证方法进行避免

function都会返回值,如果没有将会return None,注意有些方法对返回值的处理需要注意
如:list = list.append(4)


凑字数问题 可以看看
Chapter Quiz
1. What is the difference between enclosing a list comprehension in square brackets and parentheses?

2. How are generators and iterators related?

3. How can you tell if a function is a generator function?

4. What does a yield statement do?

5. Given a function object, and a tuple of arguments, how might you call the function?

6. How are map calls and list comprehensions related? Compare and contrast the two.

7. How are lambda expressions and def statements related? Compare and contrast
the two.

Quiz Answers

1. List comprehensions in square brackets produce the result list all at once in
memory. When they are enclosed in parentheses instead, they are actually generator
expressions—they have a similar meaning, but do not produce the result list
all at once. Instead, generator expressions return a generator object, which yields one item in the result at a time when used in an iteration context.

2. Generators are objects that support the iteration protocol—they have a next
method that repeatedly advances to the next item in a series of results, and raises an exception at the end of the series. In Python, we can code generator functions with def, generator expressions with parenthesized list comprehensions,
and generator objects with classes that define a special method named _ _iter_ _
(discussed later in the book).

3. A generator function has a yield statement somewhere in its code. Generator
functions are otherwise identical to normal functions.

4. When present, this statement makes Python compile the function specially as a
generator; when called, it returns a generator object that supports the iteration
protocol. When the yield statement is run, it sends a result back to the caller, and suspends the function’s state; the function can then be resumed in response to a next method call at the caller continuing after the last yield statement. Generator functions may also have a return statement, which terminates the generator.

5. You can call the function generically with the apply-like call syntax:
function(*argstuple). You can also use the built-in function apply(function,
args), but this built-in will likely be removed in a future Python release, and is
not as general.


6. The map call is similar to a list comprehension—both build a new list by collecting the results of applying an operation to each item in a sequence or other iterable, one item at a time. The main difference is that map applies a function call to each item, and list comprehensions apply arbitrary expressions. Because of this, list comprehensions are more general; they can apply a function call expression like map, but map requires a function to apply other kinds of expressions.List comprehensions also support extended syntax such as nested for
loops and if clauses that subsume the filter built-in.

7. Both lambda and def create function objects to be called later. Because lambda is an expression, though, it can be used to nest a function definition in places
where a def will not work syntactically. Using a lambda is never required—you
can always code a def instead, and reference the function by name. lambdas come
in handy, though, to embed small pieces of deferred code that are unlikely to be
used elsewhere in a program. Syntactically, a lambda only allows for a single
return value expression; because it does not support a block of statements, it is
not ideal for larger functions.
































































分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics