中所谓的使用函数,(必威手机官网4)可变参数

当def函数参数默认值为对象时,例如列表[],字典{}

二、函数

python 在调用时计算默认值

大家都知道python的默认值是在函数定义时计算出来的, 也就是说默认值只会计算一次, 之后函数调用时, 如果参数没有给出,

同一个值会赋值给变量, 这会导致, 如果我们想要一个list默认值, 新手通常这么写:

 

def foo(a=[]):

 a.append(3)

 print a

其实是错误的,两次调用会这样的结果:

 

[3]

[3, 3]

其实应该这么写

 

def baz(a=None):

   a = a or []

    a.append(3)

    print a

两次调用输出以下结果:

 

[3]

[3]

 

 

 

 

这样好挫啊, 搞的虽然有默认值用法,但是我们却需要写的和js,lua一样, 我们不能像c++一样, 在函数运行时每次执行默认值么.

用decorator可以模拟下

 

复制代码

import functools

import copy

def compute_default_value_for_each_call(func):

    defaults = func.__defaults__

    if not defaults:

        return None

    defaults = tuple(copy.copy(x) for x in defaults)

 

    @functools.wraps(func)

    def wrapper(*args, **kwargs):

        if func.__defaults__ != defaults:

            func.__defaults__ = tuple(copy.copy(y) for y in defaults)

        return func(*args, **kwargs)

 

    return wrapper

 

 

@compute_default_value_for_each_call

def foo(b, a=[]):

    if b:

        a.append(3)

    return a

 

import timeit

复制代码

这样两次调用foo(1), 结果为:

 

[3]

[3]

这个decorator有对未修改默认参数值做优化, 在我们不对默认值修改的情况下(比如打印变量a的内容), 性能有很大提升:

 

复制代码

@compute_default_value_for_each_call

def foo(b, a=[]):

    if b:

        a.append(3)

    return a

 

 

def foo2(b, a=None):

    a = a or []

    if b:

        a.append(3)

    return a

 

import timeit

 

print timeit.timeit('foo(1)', setup='from __main__ import foo')

print timeit.timeit('foo(0)', setup='from __main__ import foo')

print timeit.timeit('foo2(1)', setup='from __main__ import foo2')

print timeit.timeit('foo2(0)', setup='from __main__ import foo2')

复制代码

执行结果(调用1000000次的总时间)

 

4.32704997063

0.630109071732

0.445858955383

0.26370882988

性能上还过得去....

在调用时计算默认值 大家都知道python的默认值是在函数定义时计算出来的, 也就是说默认值只会计算一次, 之后函数调用时, 如果参数...

1.参数的介绍

(1)可变和不可变参数

(2)必选参数

(3)默认参数

(4)可变参数

(5)关键字参数


必威手机官网 1

 

 

1.1.可变和不可变参数

分享给大家的11道Python面试题,好多小伙伴都很积极的去思考分析,给我留言的同学非常多,非常欣慰有这么多好学的小伙伴,大家一起学习,一起加油,把Python学好,今天我就把11道面试题细细解答一下

示例1:猜测一下,会输出什么??? 

2.1、重新认识函数

不可变类型:

类似 c++ 的值传递,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。

分别阐述3种引号用的场景和区别

def ddd(a,b=[]):
    b.append(a)
    return b

print(ddd(1))
print(ddd(2,['a','b','c']))
print(ddd(3))

必威手机官网 2

可变类型:

类似 c++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响

引用。


1),单引号和双引号主要用来表示字符串

 

     Python 中所谓的使用函数,就是把你要处理的对象放到一个名字后面的括号里。简单来说,函数就是这么使用的,往里面塞东西就可以得到处理结果。

1.2.必选参数

必选参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。

例如:

def f(a,b):

print('jjjjjj')

return a+b

print(f(1,2))

输出结果为:

jjjjjj


比如:

[1]  ['a','b','c','2'] [3]   ?????你是否认为是这样? 输出一下看看

 

1.3.默认参数

调用函数时,缺省参数的值如果没有传入,则被认为是默认值

例如:

def f(a,b=100):

    print('********************')

    return a+b

print(f(1))

print(f(1,b=20))

print(f(1,3))

print('############################$$$#############################')

def f(a=100,b=200):

    print('****************')

    return a+b

print(f(1,2))

print(3,2)

print(f())

print(f(3))

输出结果为:

********************

101

********************

21

********************

4

############################$$$#############################

****************

3

3 2

****************

300

****************

203


单引号:'python'

输出结果:

- Python 的 内建函数(Built-in Functions)

1.4.可变参数-元组

在Python函数中,还可以定义可变参数。顾名思义,可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。参数组装成一个tutple

def calc(*numbers):

    sum = 0

   for n in numbers:

        sum = sum + n * n

        return sum

例如:

def f(*num):

    print(num)

f(1,2,3,4,5)

f(100,101)

f(111)

f([1,2,3,4],None,True,{'a':4})

f()

print('***********************************$$$**********************************')

def f1(*args):

    print(sum(args))

num1=1

num2=2

num3=3

f1(num1,num2,num3)

ls=[1,2,3,4,5]

f1(ls[0],ls[1],ls[2],ls[3],ls[4])

ls=[i for i in range(10)]

f(*ls)

f(ls)

输出结果为:

(1, 2, 3, 4, 5)

(100, 101)

(111,)

([1, 2, 3, 4], None, True, {'a': 4})

()

***********************************$$$**********************************

6

15

(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

([0, 1, 2, 3, 4, 5, 6, 7, 8, 9],)

45


双引号:"python"

D:Python27python.exe D:/untitled1/temp5.py
[1]
['a', 'b', 'c', 2]
[1, 3]

 

1.5.可变参数-字典

变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。

def person(name, age, **kw):

    print('name:', name, 'age:', age, 'other:', kw)

例如:

def f(**kvs):

    print(kvs)

f(a=1,b='abc',c=[1,2,3])

infos={'a':1,'b':2}

f(**infos)

输出结果为:

{'c': [1, 2, 3], 'a': 1, 'b': 'abc'}

{'a': 1, 'b': 2}

=


2).三引号

 

以 Python 3.60 版本为例,一共存在 68 个这样的函数,它们被统称为 内建函数(Built-in Functions)。

1.6.关键字参数

对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。至于到底传入了哪些,就需要在函数内部通过kw检查。

注意:如果要限制关键字参数的名字,就可以用命名关键字参数。

def person(name, age, *, city, job):

    print(name, age, city, job)

例如:

def f(a,b):

    print('a=%s,b=%s'%(a,b))

f(b=1,a=2)

输出结果为:

a=2,b=1


三单引号:'''python ''',也可以表示字符串一般用来输入多行文本,或者用于大段的注释

看到以上结果有什么想法,为什么呢???[1, 3]而不是[3],那么修改一下代码,输出b变量的内存地址看一下。我想,可以找到我要的答案

之所以被称为内建函数,并不是因为还有“外建函数”这个概念,“内建”的意思是在 Python 3.60 版本安装完成后,你无须创建就可以直接使用这些函数,即 表示这些函数是“自带”的而已。

1.7.参数组合

在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。但是请注意,参数定义的顺序必须是:

必选参数、默认参数、可变参数。

例如:

def f(a,b=1,*c,**d):

print(a)

print(b)

print(c)

print(d)

f(1,2,3,4,5,6,dd=100,bb=30)

输出结果为:

1

2

(3, 4, 5, 6)

{'bb': 30, 'dd': 100}

=


三双引号:"""python""",一般用在类里面,用来注释类,这样省的写文档,直接用类的对象__doc__访问获得文档

def ddd(a,b=[]):
    b.append(a)
    print(id(b)) #查看内存地址
    return b

print(ddd(1))
print(ddd(2,['a','b','c']))
print(ddd(3))

 

1.8.变量作用域介绍

一个程序的所有的变量并不是在哪个位置都可以访问的。访问权限决定于这个变量是在哪里赋值的。

变量的作用域决定了在哪一部分程序你可以访问哪个特定的变量名称。两种最基本的变量作用域如下:

区别:

输出结果:

Python 3.60 的 68个 内建函数(Built-in Functions):

全局变量

若你的字符串里面本身包含单引号,必须用双引号

D:Python27python.exe D:/untitled1/temp5.py
170580872
[1]
171586568
['a', 'b', 'c', 2]
170580872
[1, 3]
    Built-in Functions    
abs() dict() help() min() setattr()
all() dir() hex() next() slice()
any() divmod() id() object() sorted()
ascii() enumerate() input() oct() staticmethod()
bin() eval() int() open() str()
bool() exec() isinstance() ord() sum()
bytearray() filter() issubclass() pow() super()
bytes() float() iter() print() tuple()
callable() format() len() property() type()
chr() frozenset() list() range() vars()
classmethod() getattr() locals() repr() zip()
compile() globals() map() reversed() __import__()
complex() hasattr() max() round()  
delattr() hash() memoryview() set()  

局部变量

比如:"can't find the logn"

从输出中,可以看出,除了,第二个print,其它两个内存是一们的。那么考虑一下为什么第二个为被改变。结果显而易见,因为第二个print改变了,b对象,重新创建了一个对象。

 

(1).局部变量

局部变量,就是在函数内部定义的变量

不同的函数,可以定义相同的名字的局部变量,但是各用个的不会产生影响

局部变量的作用,为了临时保存数据需要在函数中定义变量来进行存储,这就是它的作用

举例说明Python函数参数传递的几种形式,并说明函数传参是值传递还是引用传递

 

 

(2).全局变量

如果一个变量,既能在一个函数中使用,也能在其他的函数中使用,这样的变量就是全局变量

如果要再函数中修改全局变量,使用global声明。

例如:

a=100

print(a)

print('******************************')

def f():

    a=200

f()

print(a)

以上代码中,定义了一个全局变量,a=100,定义了一个没有返回值和参数的函数f,在函数中定义了一个局部变量a=200。

输出结果为:

100

******************************

100

第二个结果,虽然有局部变量但是没有被调用,调用的还是全局变量a=100.

def f(a):

    print('num=%s'%num)

num=111

f(100)

print(num)

输出结果为:

num=111

111

以上代码,定义了一个全局变量,而没有局部变量,num=111,当f=100时,会输出num=111.

def f(num):

    print('num=%s'%num)

num=111

f(100)

print(num)

输出结果为:

num=100

111

以上代码,定义了一个局部变量个一个全局变量,就近原则有限使用局部变量。

def f(num):

    num+=1

    print('num=%s'%num)

num=111

f(100)

print(num)

输出结果为:

num=101

111

以上代码,有一个局部变量,和一个全局变量,在函数运行时,调用了局部变量,此时的全局变量并没有变。

num=111

def f():

    global num

    print('num1=%s'%num)

    num+=1

    print('num2=%s'%num)

f()

print('num3=%s'%num)

输出结果为:

num1=111

num2=112

num3=112

以上代码中,global num 定义了一个全局变量,此时为全局变量。此时的全局变量已经改变。

=


1).Python的参数传递有:

那么如果不想出现,每次调用,默认值对象不变的问题,可以这样改一下:

2.2、创建函数

1.9.全局和局部变量重名

如果全局变量的名字和局部变量的名字相同,那么使用的是局部变量

在函数外边定义的变量叫做全局变量

全局变量能够在所以的函数中进行访问

如果在函数中修改全局变量,那么就需要使用global进行声明

如果全局变量的名字和局部变量的名字相同,那么使用的是局部变量的,

小技巧强龙不压地头蛇

=


位置参数

def ddd(a,b=None):
    if type(b).__name__!='list':
        b = []

    b.append(a)
    print(id(b)) #查看内存地址
    return b

print(ddd(1))
print(ddd(2,['a','b','c']))
print(ddd(3))

 

1.10.递归函数

如果一个函数在内部不调用其它的函数,而是自己本身的话,这个函数就是递归函数。

满足递归的条件:

有循环的内容

有跳出的条件

递归默认是有递归深度要求的。

=


默认参数,

初始值设置为None,通过类型判断来,进行内处理

- Python 创建函数的格式如下:

1.11.匿名函数

用lambda关键词能创建小型匿名函数。这种函数得名于省略了用def声明函数的标准步骤。

lambda函数的语法只包含一个语句,如下:

lambda [arg1 [,arg2,.....argn]]:expression

注意:

Lambda函数能接收任何数量的参数但只能返回一个表达式的值

可变参数,

 

 

关键字参数

小结:

必威手机官网 3

2).函数的传值到底是值传递还是引用传递,要分情况

       1.python定义def的时候,如果参数做为对象,那么,如果没有改变这个对象的前提下,那么即使,多次调用该函数也,不会创建新的对象。

 

a.不可变参数用值传递:

          那么就会出现多次调用函数,有可能都进行了处理。

 

像整数和字符串这样的不可变对象,是通过拷贝进行传递的,因为你无论如何都不可能在原处改变不可变对象

  2.如果,没有特殊需求,函数参数,尽量不采用对象,如果一有需要,对象进行内处理。传默认值None

★ 重 点:

b.可变参数是用引用传递的

 

  ① def(即 define ,定义)的含义是创建函数,也就是定义一个函数。

比如像列表,字典这样的对象是通过引用传递,和C语言里面的用指针传递数组很相似,可变对象能在函数内部改变.

  ② 闭合括号后面的 冒号( )必不可少。

举例说明lambda的用法,并说明用lambda的优点

  ③ 函数「缩进」后面的语句被称作 语句块(block),缩进是为了表明语句和逻辑的从属关系,是 Python 最显著的特征之一。(大部分语言会用大括号 { } 来表明这样从属关系)

1).lambda的用法:

  ④ return 即返回结果。在 Python 中 return 是可选的,如果没有 return 即函数的返回值为 ‘None’。 

lambda是匿名函数,用法如下:lambda arg1,arg2..argN:expression using args

 

2).优点

☆ 注意:

lambda能和def做同样种类的工作,特别是对于那些逻辑简单的函数,直接用lambda会更简洁,而且省去取函数名的麻烦(给函数取名是个技术活)

  ① def 和 return 是 关键字(keyword),Python 就是靠识别这些特定的关键字来明白用户的意图,实现更为复杂的编程。

字符串的format函数非常灵活,很强大,可以接受的参数不限个数,并且位置可以不按顺序,而且有较为强大的格式限定符(比如:填充,对齐,精度等)

本文由必威发布于必威-编程,转载请注明出处:中所谓的使用函数,(必威手机官网4)可变参数

相关阅读