函数1



1 函数概念

1.1 函数特点

1.2 如何定义函数

语法

def func_name(arg1, arg2 ...):
...code...
return result

>>> def say():
...     print 'first print.'
...     return
...     print 'second print'
...

>>> say()
first print.

# 第二个print之所以没有输出是因为在return语句处函数已经结束

1.3 函数作用域

作用域影响演示

>>> a = 1
>>> def use_a():
...     a = 2
...     print a
...
>>> use_a()
2
>>> a
1

# 新建函数use_a()中对a的赋值并未改变主程序中的a变量,这就是按代码块区分的作用域

我们可以通过在函数定义中使用global来使变量全局化来调用

>>> a = 1
>>> def use_a():
...     a = a * 2
...     print a
...
>>> use_a()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in use_a
UnboundLocalError: local variable 'a' referenced before assignment

>>> def use_a():
...     global a
...     a = a * 2
...     print a
...
>>> use_a()
2
>>> a
2            # <-----------改变了主程序中a的值
# 不推荐global,原因是会对其他使用此变量的函数造成不可预料的影响

global:把本地变量或者主程序变量声明成全局变量。

>>> a = 'main level'
>>> def test():
...     a = 'second level'
...     def test_inside():
...         global a          # <----在第三层级代码块global a变量
...         print a
...     test_inside()
...
>>> test()
main level   
# 说明global可以全局主程序中的变量

# 继续尝试
>>> del a
>>> test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in test
  File "<stdin>", line 5, in test_inside
NameError: global name 'a' is not defined
# 说明global不可以声明主程序与本函数之间的变量

# 继续尝试
>>> def test():
...     def test2():
...         a = 'this is from test2()'
...         global a
...     test2()
...     print a
...
<stdin>:4: SyntaxWarning: name 'a' is assigned to before global declaration     # 有报错,写法不推荐,只为演示用
>>> test()
this is from test2()

# 说明global只能声明主程序或者本身函数的本地变量

2 函数参数

参数命名不可重复,包括位置参数和关键字参数

2.1 如何定义和传递参数

# 定义函数、传参数
>>> def say(words):
...     print words
...

>>> say('hello world!')
hello world!
>>> a = 'hello world again!'
>>> say(a)
hello world again!

# 传多个参数
>>> def say(who,words):
...     print '%s say %s'% (who,words)
...

>>> say('wo','I WANT GO TO MOON')
wo say I WANT GO TO MOON

# 关键字参数的使用
>>> def say(who,words='$500W'):
...     print '%s earn %s' %(who,words)
...
>>> say('good')
good earn $500W

# 关键字参数必须在位置参数的后面
>>> def say(who='XiJinping',words)
  File "<stdin>", line 1
    def say(who='XiJinping',words)
                                 ^
SyntaxError: invalid syntax

# 默认参数值不要使用引用
>>> def append_list(element, to=[]):
...     to.append(element)
...     print to
...     return to
...
>>> list1 = append_list(3)
[3]
>>> list1 = append_list(4)
[3, 4]
# 因为函数的关键字参数是在函数被定义的时候初始化的,并不是在被调用的时候

# 我们可以这样修改去解决
>>> def append_list(element, to=None):
...     to = to or []
...     to.append(element)
...     print to
...     return to
...
>>> list1 = append_list(3)
[3]
>>> list2 = append_list(4)
[4]

形参和实参

  • 形参:定义函数时使用的参数名称
  • 实参:使用函数时传递的参数值

2.2 n个参数怎么处理?

# 不确定的多参数传递
>>> def say(who,*words):
...     print who,'say',words
...
>>> say('Mr Mao','sun','rise','east')
Mr Mao say ('sun', 'rise', 'east')            
# 结果是一个tuple

# 参数传递给变量
>>> def say(*words):
...     first_word, second_word = words
...     print first_word,'\n',second_word
...
>>> say('good','morning')
good
morning
# 但是这样不靠谱,如下
>>> say('good','morning','ah')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in say
ValueError: too many values to unpack
# 因为你无法确定输入端会按照你定义的变量数量进行输入

# 如何接受多元的参数(多元参数位置必须在其他类型参数后面)
>>> def say(*words,**info):
...     print words, info
...
>>> say('The 5th ','team is :',name='Jiulong',num=250)
('The 5th ', 'team is :') {'num': 250, 'name': 'Jiulong'}
# 多元参数传递过来以后就是个dict
# 还可以直接传dict
>>> say('The 5th ','team is :',**{'name':'Jiulong','num':250})
('The 5th ', 'team is :') {'num': 250, 'name': 'Jiulong'}

2.3 可变对象和不可变对象在函数中引用的区别

函数

>>> def modify(key):
...     key += 'good'
...

不可变对象

>>> s = 'bad'
>>> modify(s)
>>> s
'bad'              # 字符串(不可变对象)变量s没有改变。

可变对象

>>> l = ['bad']
>>> modify(l)
>>> l
['bad', 'g', 'o', 'o', 'd']

2.4 “值传递”和”引用传递”

2.3 中的函数其实就是引用传递,只是传递了个内存地址,所以会对原变量产生影响,但是如果我们修改它为值传递

>>> def modify(key):
...     key = key[:]
...     key += 'good'
...     print key
...
>>> l = ['bad']
>>> modify(l)
['bad', 'g', 'o', 'o', 'd']
>>> l
['bad']
# 此时原变量不会更改
def change_name(person):
     person['name'] = 'the5fire'             # 这样不好,why?
     # person.update({'name': 'the5fire'})   # 要这样

t = {"name": 'huyang', 'age': 10}
change_name(t)
print t  #结果是?

3. 练习题

3.1 修改第三节的习题,实现两个函数,一个用来判断是否为数字(包括浮点型),一个用来判断是否为素数。然后使用这两个函数重构习题代码。

#!/usr/bin/python
#Filename:is_prime_def.py
''' aim to find all prime from 0 to the number user give. '''
def is_num(x):
    try:
        int(x)
        return 1
    except ValueError:
        return 0

def is_prime(y):
    if is_num(y):
        y = int(y)
        if y > 1:
            for i in range(2,y//2+1):
                if y % i == 0:
                    return 0
                    break
                else:
                    return 1
        else:
            print "number must bigger than 1!"
    else:
        print "you must input a number!"

while True:
    input_user = raw_input('Input a number :').strip()
    if is_num(input_user):
        input_user = int(input_user)
    else:
        print 'you must input a number'
        continue

    print '==========start========'
    for num_prime in range(2,input_user + 1):
        if is_prime(num_prime):
            print "prime : %d" % num_prime
    break
print '==========Done========'

3.2 修改上一节统计字符的程序,实现一个函数,接受参数是字符串,输出是字典–字典key是字母,value是出现频率,使用函数完成功能

# coding=utf-8
#!/usr/bin/pythonp
# Filename:test_05.py
s = '''
Have you thought about what you want people to say about you after you're gone? Can you hear the voice saying, "He was a great man." Or "She really will be missed." What else do they say?
One of the strangest phenomena of life is to engage in a work that will last long after death. Isn't that a lot like investing all your money so that future generations can bare interest on it? Perhaps, yet if you look deep in your own heart, you'll find something drives you to make this kind of contribution---something drives every human being to find a purpose that lives on after death.
'''

def str_to_dict(str_in):
    # dereplication string
    str_list_unique = list(set(str_in))
    str_list = list(str_in)
    letter_unique = [x for x in str_list_unique if x.isalpha()]
    # make a dict by zip() to store the result of count
    return dict(zip(letter_unique,[str_list.count(y) for y in letter_unique]))

# count how many letters in string s
#s=s.lower()
letter_keep = [i for i in s if i.isalpha()]
print 'Total letter : %s' % len(letter_keep)

letter_dict = sorted(str_to_dict(s).items(), key=lambda x:x[1],reverse=True)
for j in range(len(letter_dict)):
    print '%-s: %s' %(letter_dict[j][0],letter_dict[j][1])