Python函数。。

  • Post author:
  • Post category:python


1.函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段

2.语法:

def 函数名(参数列表):

函数体

return XXX

可以返回多个值,返回的多个值组成一个元组,返回值加上一对中括号,则返回一个列表

函数分为定义和调用

练习:定义一个函数,实现两个数字的加、减、乘、除

3.可更改(mutable)与不可更改(immutable)对象

在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象。

不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变a的值,相当于新生成了a。

可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。

python 函数的参数传递:

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

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

4.以下是调用函数时可使用的正式参数类型:

必需参数

关键字参数:关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict

例:# 关键字参数:**kw

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

print(‘name:’,name,’age:’,age,’other:’,kw)

person(‘Frank’,’37’)

person(‘Frank’,’37’,city=’Shanghai’)

person(‘Frank’,’37’,gender=’M’,job=’Engineer’)

也可以写成下面的简约形式:

extra = {‘city’: ‘Beijing’, ‘job’: ‘Engineer’}

person(‘Jack’, 24, **extra)

注意kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra。

默认参数:(缺省参数)缺省参数必须写在后面,可以不指定参数名,但是顺序要保证,否则要指定参数名

#可写函数说明

def printinfo( name, age = 35 ):

“打印任何传入的字符串”

print (“名字: “, name);

print (“年龄: “, age);

return;

#调用printinfo函数

printinfo( age=50, name=”runoob” );

print (“————————“)

printinfo( name=”runoob” );

不定长参数(可变参数):

可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple

def calc(numbers):

sum = 0

for n in numbers:

sum = sum + n * n

return sum

但是调用的时候,需要先组装出一个list或tuple:

>>> calc([1, 2, 3])

14

>>> calc((1, 3, 5, 7))

84

如果利用可变参数,调用函数的方式可以简化成这样:

>>> calc(1, 2, 3)

14

>>> calc(1, 3, 5, 7)

84

所以,我们把函数的参数改为可变参数:

def calc(*numbers):

sum = 0

for n in numbers:

sum = sum + n * n

return sum

定义可变参数和定义一个list或tuple参数相比,仅仅在参数前面加了一个*号。在函数内部,参数numbers接收到的是一个tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数:

>>> calc(1, 2)

5

>>> calc()

0

如果已经有一个list或者tuple,要调用一个可变参数怎么办?可以这样做:

>>> nums = [1, 2, 3]

>>> calc(nums[0], nums[1], nums[2])

14

这种写法当然是可行的,问题是太繁琐,所以Python允许你在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去:

>>> nums = [1, 2, 3]

>>> calc(*nums)

14

*nums表示把nums这个list的所有元素作为可变参数传进去。这种写法相当有用,而且很常见。

参数组合

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

比如定义一个函数,包含上述若干种参数:

def f1(a, b, c=0, *args, **kw):

print(‘a =’, a, ‘b =’, b, ‘c =’, c, ‘args =’, args, ‘kw =’, kw)

def f2(a, b, c=0, *, d, **kw):

print(‘a =’, a, ‘b =’, b, ‘c =’, c, ‘d =’, d, ‘kw =’, kw)

最神奇的是通过一个tuple和dict,你也可以调用上述函数:

>>> args = (1, 2, 3, 4)

>>> kw = {‘d’: 99, ‘x’: ‘#’}

>>> f1(*args, **kw)

a = 1 b = 2 c = 3 args = () kw = {‘d’: 99, ‘x’: ‘#’}

>>> args = (1, 2, 3)

>>> kw = {‘d’: 88, ‘x’: ‘#’}

>>> f2(*args, **kw)

a = 1 b = 2 c = 3 d = 88 kw = {‘x’: ‘#’}

所以,对于任意函数,都可以通过类似func(*args, **kw)的形式调用它,无论它的参数是如何定义的。

return xxx,xxx,xxx

将返回一个元组

调用函数时返回几个值也可以用几个变量接收

def f3(a,b,c=0,d=None):

print(c,d)

f3(1,2,d=5)#命名参数

def f4(a,b):

a,b=11,12

return a,b#当返回多个值时,自动组成一个元组

c,d=f4(1,2)#也可以使用多个变量接收

小结

Python的函数具有非常灵活的参数形态,既可以实现简单的调用,又可以传入非常复杂的参数。

默认参数一定要用不可变对象,如果是可变对象,程序运行时会有逻辑错误!

要注意定义可变参数和关键字参数的语法:

*args是可变参数,args接收的是一个tuple;

**kw是关键字参数,kw接收的是一个dict。

变量作用域:

全局变量与局部变量的作用域不同

生命周期不同

全局变量:

g_a=10

def test2():

global g_a#告诉程序这里是一个全局变量

g_a=20

print(g_a)

def test3():

print(g_a)

test2()

test3()

当全局变量和局部变量同名时,局部变量优先

局部变量

当列表和字典作为全局变量时,不用加global

匿名函数:

python 使用 lambda 来创建匿名函数

语法:lambda [arg1 [,arg2,…..argn]]:expression

# 可写函数说明

sum = lambda arg1, arg2: arg1 + arg2;

sum(1,2)

def XXX(arg1,arg2):

return arg1+arg2

sum=XXX(10,20)

# 调用sum函数

print “相加后的值为 : “, sum( 10, 20 )

print “相加后的值为 : “, sum( 20, 20 )

def add(a,b,fun):

print(fun(a,b))

add(11,22,lambda arg1, arg2: arg1 – arg2)

案例:

对于简单的函数,也存在一种简便的表示方式,即:lambda表达式

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

# ###################### 普通函数 ######################

# 定义函数(普通方式)

def func(arg):

return arg + 1

# 执行函数

result = func(123)

# ###################### lambda ######################

# 定义函数(lambda表达式)

my_lambda = lambda arg : arg + 1

# 执行函数

result = my_lambda(123)

三个重要的大数据用到的函数:

>>> foo = [2, 18, 9, 22, 17, 24, 8, 12, 27]

>>> print filter(lambda x: x % 3 == 0, foo)

[18, 9, 24, 12, 27]

>>> print map(lambda x: x * 2 + 10, foo)

[14, 46, 28, 54, 44, 58, 26, 34, 64]

>>> print reduce(lambda x, y: x + y, foo)

139

蜗牛 2018/5/29 12:29:34

三个重要的大数据用到的函数:

>>> foo = [2, 18, 9, 22, 17, 24, 8, 12, 27]

>>> print filter(lambda x: x % 3 == 0, foo)

[18, 9, 24, 12, 27]

>>> print map(lambda x: x * 2 + 10, foo)

[14, 46, 28, 54, 44, 58, 26, 34, 64]

>>> print reduce(lambda x, y: x + y, foo)

139

python map()

map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。

举例说明,比如我们有一个函数f(x)=x%2,要把这个函数作用在一个list [1, 2, 3, 4, 5, 6, 7, 8, 9]上,就可以用map()实现

#使用lambda函数

案例1:

print map(lambda x: x % 2, range(7))

[0, 1, 0, 1, 0, 1, 0]

案例2:

li = [11, 22, 33]

new_list = map(lambda a: a + 100, li)

python filter():对于序列中的元素进行筛选,最终获取符合条件的序列

li = [11, 22, 33]

new_list = filter(lambda arg: arg > 22, li)

例如,要从一个list [1, 4, 6, 7, 9, 12, 17]中删除偶数,保留奇数,首先,要编写一个判断奇数的函数:

def is_odd(x):

return x % 2 == 1

然后,利用filter()过滤掉偶数:

>>>filter(is_odd, [1, 4, 6, 7, 9, 12, 17])

结果:

[1, 7, 9, 17]

利用filter(),可以完成很多有用的功能,例如,删除 None 或者空字符串:

def is_not_empty(s):

return s and len(s.strip()) > 0

>>>filter(is_not_empty, [‘test’, None, ”, ‘str’, ‘ ‘, ‘END’])

结果:

[‘test’, ‘str’, ‘END’]

注意: s.strip(rm) 删除 s 字符串中开头、结尾处的 rm 序列的字符。

当rm为空时,默认删除空白符(包括’\n’, ‘\r’, ‘\t’, ‘ ‘),如下:

>>> a = ‘ 123’

>>> a.strip()

‘123’

>>> a = ‘\t\t123\r\n’

>>> a.strip()

‘123’

练习:

请利用filter()过滤出1~100中平方根是整数的数,即结果应该是:

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

方法:

import math

def is_sqr(x):

return math.sqrt(x) % 1 == 0

print filter(is_sqr, range(1, 101))

结果:

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

python reduce():对于序列内所有元素进行累计操作

li = [11, 22, 33]

result = reduce(lambda arg1, arg2: arg1 + arg2, li)

python中的reduce

python中的reduce内建函数是一个二元操作函数,他用来将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给reduce中的函数 func()(必须是一个二元操作函数)先对集合中的第1,2个数据进行操作,得到的结果再与第三个数据用func()函数运算,最后得到一个结果。

如:

def myadd(x,y):

return x+y

sum=reduce(myadd,(1,2,3,4,5,6,7))

print sum

#结果就是输出1+2+3+4+5+6+7的结果即28

当然,也可以用lambda的方法,更为简单:

sum=reduce(lambda x,y:x+y,(1,2,3,4,5,6,7))

print sum

reduce()函数也是Python内置的一个高阶函数。reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce()传入的函数 f 必须接收两个参数,reduce()对list的每个元素反复调用函数f,并返回最终结果值。

例如,编写一个f函数,接收x和y,返回x和y的和:

def f(x, y):

return x + y

调用 reduce(f, [1, 3, 5, 7, 9])时,reduce函数将做如下计算:

先计算头两个元素:f(1, 3),结果为4;

再把结果和第3个元素计算:f(4, 5),结果为9;

再把结果和第4个元素计算:f(9, 7),结果为16;

再把结果和第5个元素计算:f(16, 9),结果为25;

由于没有更多的元素了,计算结束,返回结果25。

上述计算实际上是对 list 的所有元素求和。虽然Python内置了求和函数sum(),但是,利用reduce()求和也很简单。

reduce()还可以接收第3个可选参数,作为计算的初始值。如果把初始值设为100,计算:

reduce(f, [1, 3, 5, 7, 9], 100)

结果将变为125,因为第一轮计算是:

计算初始值和第一个元素:f(100, 1),结果为101。

练习:

Python内置了求和函数sum(),但没有求积的函数,请利用reduce()来求积:

输入:[2, 4, 5, 7, 12]

输出:2*4*5*7*12的结果

方法:

def prod(x, y):

return x*y

print reduce(prod, [2, 4, 5, 7, 12])

结果:

>>>3360

python中自定义排序函数:

Python内置的 sorted()函数可对list进行排序:

>>>sorted([36, 5, 12, 9, 21])

[5, 9, 12, 21, 36]

但 sorted()也是一个高阶函数,它可以接收一个比较函数来实现自定义排序,比较函数的定义是,传入两个待比较的元素 x, y,如果 x 应该排在 y 的前面,返回 -1,如果 x 应该排在 y 的后面,返回 1。如果 x 和 y 相等,返回 0。

sorted()也可以对字符串进行排序,字符串默认按照ASCII大小来比较:

>>> sorted([‘bob’, ‘about’, ‘Zoo’, ‘Credit’])

[‘Credit’, ‘Zoo’, ‘about’, ‘bob’]

‘Zoo’排在’about’之前是因为’Z’的ASCII码比’a’小。

.sort()排序方法

shus.sort()对原有列表进行排序,改变原来列表的顺序,无返回值

print(shus)就是改变后的列表

sorted()排序函数

排序时不影响原数据,产生新的排序数据

print(sorted(shus))排序后的结果

print(shus)还是原结果

练习:

对字符串排序时,有时候忽略大小写排序更符合习惯。请利用sorted()高阶函数,实现忽略大小写排序的算法。

输入:[‘bob’, ‘about’, ‘Zoo’, ‘Credit’]

>>> a = [‘bob’, ‘about’, ‘Zoo’, ‘Credit’]

>>> print(sorted(a, key=str.lower))

结果:

[‘about’, ‘bob’, ‘Credit’, ‘Zoo’]

蜗牛 2018/5/29 12:29:53

类:具有相同的属性和方法的对象的集合。

对象:万物皆对象 var date=new Date();date.get

类和对象的关系:

类的包含属性和方法:

语法:

class 类名:

属性

方法

定义一个类:

class Person:

def eat(self):

print(“正在吃饭…”)

def sleep(self):

print(“正在睡觉…”)

创建对象:属性写在类外的情况,就是通过对象.属性,对象.方法()的方式调用

调用对象的方法:

创建多个对象:

self:

__init__(self):系统自动调用初始化方法,先生成对象,再调用此方法,再将对象赋值给引用名

初始化操作

如果做全局属性:

例:

class Person:

def __init__(self,v_name,v_age):

self.name=v_name

self.age=v_age

def say(self):

print(“hello”)

生成对象:

zhangsan=Person()

zhangsan.name=”张三”

zhangsan.age=20

zhangsan.say()

__str__():

return XXX

属性相对于类来说属于全局,每个方法都可以调用。

封装

get/set方法:不写__init__()方法

set_name(self,new_name):

self.name=new_name

get_name(self):

return self.name

案例:

class Student:

def set_name(self,name):

self.name=name

def get_name(self):

return self.name

stu=Student()

stu.set_name(“abc”)

print(stu.get_name())

公有方法:

私有方法:def __test():只能在当前类中使用,以__开头

自动销毁方法:

__del__():

XXX

当对象没有引用的时候,或程序结束的时候,程序自动调用__del__()

del 引用

可演示删除时自动调用__del__()

程序结束时自动调用__del__()

可以测试一个对象有多少个引用:

import sys

t=T()

sys.getrefcount(t)返回2

面向对象的三大特征:封装、继承、多态

继承:子类继承父类,子类可以使用父类的属性和方法,简化代码.

当生成子类对象时,先初始化父类对象,所以如果父类有__init__()方法,并且有属性时,要通过子类的构造赋值

一个类可以有多个子类

在子类中,调用父类的属性时,在__init__()方法中使用

父类.属性,或self.属性或父类.__init__(self,参数)或super(父类,self).__init__(参数)四种方法给父类传参

调用父类方法时:super().父类方法()

练习:

交通工具类:属性:名称 方法:行驶

子类:卡车,属性:载重,重写行驶的方法

子类:火车,属性:车箱个数,重写行驶的方法

总结:当子类继承父类时,子类的构造方法应该包含父类和子类共同的属性,在子类的初始化方法中,将父类的属性传递给父类,子类的属性赋值给子类

方法重写:子类继承父类时,子类的方法签名和父类一样,此时子类重写了父类的方法,当生成子类对象时,调用的是子类重写的方法

父类()

子类(父类)

三代继承:子类初始化方法需要祖父、父类及自己的属性,可以调用父类的初始化方法传参,可以重写父类的方法

构造的顺序依然先构造祖父类,再构造父类,最后构造自己

类继承object

方法重写:

如果子类重写的方法想调用父类的方法时,在子类方法中:父类.方法(self)或super().父类方法()

私有属性、私有方法:均不能在类外面被调用

多继承:类同时继承多个父类,class C(A,B),当有AB均有相同方法,而子类又重写时,调用谁的方法,如果子类没有方法,则调用哪个父类的方法?

类名.mro(),可以看到所有父类,即搜索顺序

作业:

—-DVD管理系统—-:

1.查询所有DVD

2.增加DVD

3.借出DVD

4.归还DVD

5.退出

多态:

类属性:属于类的成员,属于对象共有的

类方法:在方法上添加@classmethod

@classmethod

def class_method(cls):

可以通过类方法调用类属性,也可以通过对象调用类属性

静态方法:方法前加@staticmethod,静态方法没有参数,静态方法既和类没关系,也和对象没关系,也可以通过类和对象调用

工厂类:有一些子类,在一个类中生成很多对象,简单工厂模式

pass

__new__(cls):#用来创建对象,而且必须有返回值

return object.__new__(cls)

可以用id(cls)看地址

当有属性时,需要在__new__()中也添加属性

单例:

class singleton:

__instance=None

def __new__(cls):

if cls.__instance==None:

cls.__instance=object.__new__(cls)

return cls.__instance

else:

return cls.__instance

s=singleton()

ss=singleton()

print(id(s))

print(id(ss))

对象列表进行排序:按照什么进行排序,重写__ls__方法:

class Person:

def __init__(self,name,age):

self.name=name

self.age=age

def __str__(self):

return “姓名:%s,年龄:%d”%(self.name,self.age)

def __lt__(self, other):

if self.name==other.name:

return self.age<other.age

else:

return self.name.encode(‘gbk’)>other.name.encode(‘gbk’)

支持中文排序

peple=[Person(“abc”,20),Person(“aabc”,22),Person(“abc”,21),Person(“aabc”,23)]

peple.sort()

for m in peple:

print(m)



版权声明:本文为hm112113原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。