函数先定义函数,后调用

一、定义函数:

1、简单的规则:

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()
  • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号起始,并且缩进。
  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。

2、语法

Python 定义函数使用 def 关键字

默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配起来的。

def 函数名(param1,param2……):
"""
函数功能的描述信息
:param1:描述
:param2:描述
:return:返回值
"""
code
...
return 返回值

3、无参函数

def register():
"""注册功能"""
username = input('username: ').strip()
pwd = input('password: ').strip() with open('32.txt', 'a', encoding='utf8') as fa:
fa.write(f"{username}:{pwd}\n")
fa.flush()

4、有参函数

def sum_self(x, y):
"""求和"""
res = x+y
print(res) sum_self(1,2) #

5、空函数

你只知道你需要实现某个功能,但不知道该如何用代码实现时,你可以暂时写个空函数

def func():
pass

二、调用函数及返回值

定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。

这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从 Python 命令提示符执行。

函数名(param1、param2……)

如:

register()

1、函数运行完毕所有代码,如果函数体不写return,则会返回None。

def foo():
pass print(foo()) #None

2、函数可以返回一个或多个值(元组类型)

def func():
name = 'nick'
age = 19
hobby_list = ['read', 'run']
return name, age, hobby_list name, age, hobby_list = func()
print(name,age,hobby_list) #('nick', 19, ['read', 'run'])

三、函数的参数


1、普通参数,位置必需参数

在函数定义阶段,按照从左到右的顺序依次定义的形参,称之为位置形参。

特点:按照位置定义的形参,都必须被传值,多一个不行,少一个也不行。

def func(x, y):
print(x)
print(y)

在函数调用阶段,按照从左到右的顺序依次定义的实参,称之为位置实参。

特点:按照位置为对应的形参依次传值。

func(1, 2)

2、关键字参数

在调用函数时,按照key=value的形式为指定的参数传值,称为关键字实参。

特点:可以打破位置的限制,但仍能为指定的形参赋值。

func(y=2, x=1)
  1. 可以混用位置实参和关键字实参,但是位置实参必须在关键字实参的左边。
  2. 可以混用位置实参和关键字实参,但不能对一个形参重复赋值。
func(x, y=2)
func(y=2, x) # SyntaxError: positional argument follows keyword argument
func(x, x=1) # NameError: name 'x' is not defined

3、默认参数

在定义阶段,就已经被赋值。意味着在调用时可以不用为其赋值。位置形参必须放在默认形参的左边。

def func(x, y=10):
print(x)
print(y) func(2)

默认形参的值只在定义阶段赋值一次,也就是说默认参数的值在函数定义阶段就已经固定了。

m = 10

def foo(x=m):
print(x) m = 111
foo() #

默认参数的值通常应该是不可变类型。

def register(name, hobby, hobby_list=None):
hobby_list = [hobby]
print(f"{name} prefer {hobby_list}") register('nick', 'read') # ['read']
register('tank', 'zuipao') # [ 'zuipao']
register('jason', 'piao') # ['piao'] # 演示形参是可变类型,(列表是可变类型)
def register(name, hobby, hobby_list=None):
hobby_list = [hobby]
print(f"{name} prefer {hobby_list}") register('nick', 'read') # nick prefer ['read']
register('tank', 'zuipao') # tank prefer ['zuipao']
register('jason', 'piao') # jason prefer ['piao']o']

4、不定长参数之*

形参中的*会将溢出的位置实参全部接收,然后存储元组的形式,然后把元组赋值给*后的参数。需要注意的是:*后的参数名约定俗成为args。

def sum_self( *args):
res = 0
for num in args:
res += num
return res res = sum_self(1, 2, 3, 4)
print(res) #

注意:实参之*

实参中的*,*会将*后参数的值循环取出,打散成位置实参。以后但凡碰到实参中带*的,它就是位置实参,应该马上打散成位置实参去看。

def func(x, y, z, *args):
print(x, y, z, args) func(1, *(1, 2) , 3, 4) # 1 1 2 (3, 4)

5、不定长参数之**

形参中的**会将溢出的关键字实参全部接收,然后存储字典的形式,然后把字典赋值给**后的参数。需要注意的是:**后的参数名约定俗成为kwargs。

def func( **kwargw):
print(kwargw) func(a=5,b=3) # {'a': 5, 'b': 3}

注意:实参之**

实参中的**,**会将**后参数的值循环取出,打散成关键字实参。以后但凡碰到实参中带**的,它就是关键字实参,应该马上打散成关键字实参去看。

def func(x, y, z, **kwargs):
print(x, y, z, kwargs) func(1, 3, 4, **{'a': 1, 'b': 2} ) # 1 3 4 {'a': 1, 'b': 2}

可变长参数应用

def index(name, age, sex):
print(f"name: {name}, age: {age}, sex: {sex}") # name: nick, age: 19, sex: male def wrapper(*args, **kwargs):
print(f"args: {args}") # args: ()
print(f"kwargs: {kwargs}") # kwargs: {'name': 'nick', 'sex': 'male', 'age': 19}
index( *args, **kwargs) wrapper(name='nick', sex='male', age=19)

6、命名关键字参数

命名关键字则是在「位置参数」和「命名关键字参数」中使用,*,隔开,后面的即为命名关键字。* 后的参数必须用关键字传入。

def student(name, age, *, city, gender):
print(name, age, city, gender) student('xiaoming', 6, city='beijing', gender='male') # xiaoming 6 beijing male
student('xiaoming', 6, 'beijing', 'male') #TypeError: student() takes 2 positional arguments but 4 were given

特点:在传值时,必须按照key=value的方式传值,并且key必须命名关键字参数的指定的参数名。

def register(x, y, *, name, gender='male', age):
print(x)
print(name)
print(age) register(1, 2, name1='nick', age=19) # TypeError: register() got an unexpected keyword argument 'name1'

Python3.8 新增了一个函数形参语法, “/” 用来指明函数形参必须使用指定位置参数,不能使用关键字参数的形式。

在以下的例子中,形参 a 和 b 必须使用指定位置参数,c 或 d 可以是位置形参或关键字形参,而 e 或 f 要求为关键字形参:

def f(a, b, /, c, d, *, e, f):
print(a, b, c, d, e, f)

以下使用方法是正确的:

f(10, 20, 30, d=40, e=50, f=60)

四、函数对象

函数是第一类对象,即函数可以被当做数据处理。

def func():
print('from func') print(func) # <function func at 0x00000000026A9040>

1、函数当作参数传给一个另一函数

def func():
print('from func') def foo(m):
m() foo(func) # from func

2、函数当作另一函数的返回值

def func():
print('from func') def foo(x):
return x res = foo(func)
print(res) # <function func at 0x000000000268B040>

3、函数可以当作容器类型的元素

def func():
print('from func') function_list = [func]
function_list[0]() # from func

五、函数递归

递归的精髓在于通过不断地重复逼近一个最终的结果。

age(1)=26,age(n)=age(n-1)+2 ,求age(5)的值:

'''
...
age(5) = age(4) + 2
age(4) = age(3) + 2
age(3) = age(2) + 2
age(2) = age(1) + 2
age(1) = 26 age(n) = age(n-1) +2
age(1) = 26 # n=1
''' def age(n):
if n == 1:
return 26
res = age(n-1) + 2
return res print(f"age(5): {age(5)}")

递归的本质就是干重复的活。

lis = [1, [2, [3, [4, [5, [6, ]]]]]]

def tell(lis):
for i in lis:
if type(i) is list:
tell(i)
else:
print(i) tell(lis)

二分法的思想实现查找数字。

from random import randint

nums = [randint(1, 100) for i in range(100)]
nums = sorted(nums) def search(search_num, nums):
print(nums)
mid_index = len(nums) // 2
if not nums:
print('not exists')
return
if search_num > nums[mid_index]:
# in the right
nums = nums[mid_index + 1:]
search(search_num, nums)
elif search_num < nums[mid_index]:
# in the left
nums = nums[:mid_index]
search(search_num, nums)
else:
print('find it') search(7, nums)

六、匿名函数:

python 使用 lambda 来创建匿名函数。

所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。

  • lambda 只是一个表达式,函数体比 def 简单很多。
  • lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
  • lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
  • 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。

1、语法

lamdbda 参数 : 逻辑代码

# 可写函数说明
sum = lambda arg1, arg2: arg1 + arg2 # 调用sum函数
print ("相加后的值为 : ", sum( 10, 20 ))
print ("相加后的值为 : ", sum( 20, 20 ))

匿名函数,他没有绑定名字,使用一次即被收回,加括号既可以运行。

print(lambda x, y: x + y )  # <function __main__.<lambda>(x, y)>
res = (lambda x, y: x + y)(1, 2)
print(res) #

lambda 匿名函数也是可以使用"关键字参数"进行参数传递,也可以设定默认值。

g = lambda x=0, y=0: x ** 2 + y ** 2
print(g(2, 3))
#
print(g(2))
#
print(g(y=3))
#

2、与内置函数联用

匿名函数通常与max()、sorted()、filter()、sorted()方法联用。

1.max()

如果我们想从上述字典中取出薪资最高的人,我们可以使用max()方法,但是max()默认比较的是字典的key。

  1. 首先将可迭代对象变成迭代器对象
  2. res=next(迭代器对象),将res当做参数传给key指定的函数,然后将该函数的返回值当做判断依据
salary_dict = {
'nick': 3000,
'jason': 100000,
'tank': 5000,
'sean': 2000
} print(max(salary_dict)) # tank def func(k):
return salary_dict[k] print(max(salary_dict, key=func)) # jason
print(max(salary_dict, key=lambda name: salary_dict[name] ) ) # jason 匿名函数

2.sorted()

如果我们想对上述字典中的人,按照薪资从大到小排序,可以使用sorted()方法。

  1. 首先将可迭代对象变成迭代器对象
  2. res=next(迭代器对象),将res当做参数传给第一个参数指定的函数,然后将该函数的返回值当做判断依据。
lis = [1, 3, 2, 5, 8, 6]
sorted(lis)
print(lis) # [1, 3, 2, 5, 8, 6]
print(sorted(lis, reverse=True)) # [8, 6, 5, 3, 2, 1] salary_dict = {
'nick': 3000,
'jason': 100000,
'tank': 5000,
'sean': 2000
} print(sorted(salary_dict, key=lambda name: salary_dict[name] )) # ['sean', 'nick', 'tank', 'jason']

3.map()

如果我们想对一个列表中的某个人名做处理,可以使用map()方法。

  1. 首先将可迭代对象变成迭代器对象
  2. res=next(迭代器对象),将res当做参数传给第一个参数指定的函数,然后将该函数的返回值作为map()方法的结果之一。
name_list = ['jason', 'tank', 'sean']

res = map(lambda name: f"{name} sb", name_list)
print(list(res)) # ['jason sb', 'tank sb', 'sean sb']

4.filter()

如果我们想筛选除名字中含有'sb'的名字,我们可以使用filter()方法。

  1. 首先将可迭代对象变成迭代器对象
  2. res=next(迭代器对象),将res当做参数传给第一个参数指定的函数,然后filter会判断函数的返回值的真假,如果为真则留下。
name_list = ['nick', 'jason sb', 'tank sb', 'sean sb']

filter_res = filter(lambda name: name.endswith('sb'), name_list)
print(list(filter_res)) # ['jason sb', 'tank sb', 'sean sb']

七、内置函数

共68个:

abs()、  all()、  any()、  ascii()、  bin()、  bool()、  bytearray()、  bytes()、  callable()、  chr()、  classmethod()、  compile()、  complex()、  delattr()、 
dict()、  dir()、  divmod()、  enumerate()、  eval()、  exec()、  filter()、  float()、  format()、  frozenset()、  getattr()、  globals()、  hasattr()、  hash()、 
help()、  hex()、  id()、  input()、  int()、  isinstance()、  issubclass()、  iter()、  len()、  list()、  locals()、  map()、  max()、  memoryview()、 
min()、  next()、  object()、  oct()、  open()、  ord()、  pow()、  print()、  property()、  range()、  repr()、  reversed()、  round()、  set()、 
setattr()、  slice()、  sorted()、  staticmethod()、  str()、  sum()、  super()、  tuple()、  type()、  vars()、  zip()、  __import__()、

1.bytes():解码字符。

res = '你好'.encode('utf8')
print(res) # b'\xe4\xbd\xa0\xe5\xa5\xbd'
res = bytes('你好', encoding='utf8')
print(res) # b'\xe4\xbd\xa0\xe5\xa5\xbd'

2.chr()/ord():chr()参考ASCII码表将数字转成对应字符;ord()将字符转换成对应的数字。

print(chr(65)) #A
print(ord('A')) #

3.divmod():分栏。

print(divmod(10, 3)) #(3, 1)

4.enumerate():带有索引的迭代。

l = ['a', 'b', 'c']
for i in enumerate(l):
print(i) # (0, 'a')
# (1, 'b')
# (2, 'c')

5.eval():把字符串翻译成数据类型。

lis = '[1,2,3]'
lis_eval = eval(lis)
print(lis_eval) #[1, 2, 3]

6.hash():是否可哈希。

print(hash(1)) #

7.abs():求绝对值。

print(abs(-13))  #

8.all():可迭代对象内元素全为真,则返回真。

print(all([1, 2, 3, 0])) #False
print(all([])) #True

9.any():可迭代对象中有一元素为真,则为真。

print(any([1, 2, 3, 0])) #True
print(any([])) #False

10.bin()/oct()/hex():二进制、八进制、十六进制转换。

print(bin(17)) #0b10001
print(oct(17)) #0o21
print(hex(17)) #0x11

11.dir():列举出所有time的功能。

import time
print(dir(time))
# ['_STRUCT_TM_ITEMS', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'altzone', 'asctime', 'clock', 'ctime', 'daylight', 'get_clock_info', 'gmtime', 'localtime', 'mktime', 'monotonic', 'perf_counter', 'process_time', 'sleep', 'strftime', 'strptime', 'struct_time', 'time', 'timezone', 'tzname', 'tzset']

12.frozenset():不可变集合。

s = frozenset({1, 2, 3})
print(s) #({1, 2, 3})

13.globals()/loacals():查看全局名字;查看局部名字。

# print(globals())
def func():
a = 1
# print(globals())
print(locals()) func() # {'a': 1}

14.pow():

print(pow(3, 2, 3))  # (3**2)%3 =0

15.round():

print(round(3.5)) #

16.slice():

lis = ['a', 'b', 'c']
s = slice(1, 4, 1)
print(lis[s]) #['b', 'c']
# print(lis[1:4:1])

17.sum():

print(sum(range(100))) #

18.__import__():通过字符串导入模块。

m = __import__('time')
print(m.time()) #1556607502.334777

19. 面向对象知识点

  1. classmethod
  2. staticmethod
  3. property
  4. delattr
  5. hasattr
  6. getattr
  7. setattr
  8. isinstance()
  9. issubclass()
  10. object()
  11. super()

11、Python函数基础(定义函数、函数参数、匿名函数)的更多相关文章

  1. JavaScript基础精华02(函数声明,arguments对象,匿名函数,JS面向对象基础)

    函数声明 JavaScript中声明函数的方式:(无需声明返回值类型) function add(i1, i2) {             return i1 + i2;//如果不写return返回 ...

  2. PHP匿名函数如何理解,什么是匿名函数

    揭秘PHP匿名函数 定义:匿名函数就是没有名字的函数. 有2种形式的匿名函数: 形式1:将一个匿名函数"赋值"给一个变量——此时该变量就代表该匿名函数了! 形式2: 是直接将一个匿 ...

  3. Python基础之定义有默认参数的函数

    1. 构建有默认参数的函数 当我们在构建一个函数或者方法时,如果想使函数中的一个或者多个参数使可选的,并且有一个默认值,那么可以在函数定义中给参数指定一个默认值,并且放到参数列表的最后就行了.比如: ...

  4. python基础编程: 编码补充、文件操作、集合、函数参数、函数递归、二分查找、匿名函数与高阶函数

    目录: 编码的补充 文件操作 集合 函数的参数 函数的递归 匿名函数与高阶函数 二分查找示例 一.编码的补充: 在python程序中,首行一般为:#-*- coding:utf-8 -*-,就是告诉p ...

  5. python 函数基础 定义

    一.函数介绍 1.为什么要有函数? 没有函数的代码组织结构不清晰,可读性差. 代码冗余 管理维护难度大,扩展性 2.什么是函数? 具备某一个功能的工具就是程序中的函数. 事先准备工具的过程就是:函数的 ...

  6. Python基础-列表推导式、匿名函数、os/sys/time/datetime/pymysql/xlwt/hashlib模块

    列表推导式 [表达式 for 变量 in range(n) if 条件]  等效于 for 变量 in in range(n): if 条件: 表达式 优点:书写方便,缺点:不易读 注意:用的是方括号 ...

  7. python基础之函数式编程、匿名函数、内置函数

    一 函数式编程 不修改外部状态. 模仿数学里得函数进行编程. 用函数编程写出得代码相当精简. 可读性比较差. 例子: y=2*x+1 x=1 def test(x): return 2*x+1 tes ...

  8. python第三十四课——1.匿名函数的定义和使用

    演示匿名函数的定义和使用 # 定义无参有返回值的有名函数: def func(): return True # 定义无参有返回值的匿名函数 f=lambda : True # 调用有名函数执行 pri ...

  9. Python多线程运行带多个参数的函数

    在python中经常会到用多线程处理某个函数来缩短运行时间. from multiprocessing import Pool def work(x): return x+1 pool = Pool( ...

  10. python 3.6.5 map() max() lambda匿名函数

    python 3.6.5 sample: map() 会根据提供的函数对指定序列做映射. 第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 functi ...

随机推荐

  1. Android 及 iOS 常用操作命令

    应用相关 1. 安装应用(真机) Android adb install xxx.apk iOS ideviceinstaller -i xxx.ipa 2. 卸载应用(真机) Android adb ...

  2. Background Suppression Network for Weakly-supervised Temporal Action Localization [Paper Reading]

    研究内容:弱监督时域动作定位 结果:Thumos14 mAP0.5 = 27.0 ActivityNet1.3 mAP0.5 = 34.5 从结果可以看出弱监督这种瞎猜的方式可以PK掉早些时候的一些全 ...

  3. 运行带有Activiti modeler时,出现这样的报错: java.rmi.AccessException: Cannot modify this registry

    最近在做整合Activiti Modeler工作流在线设计器的工作,运行IDEA时,出现了这样一个错误信息: 原因及解决办法:   Activiti默认打开了jmx功能,默认端口为1099,idea中 ...

  4. linux或者shell进入vi命令

    vi的基本操作 a) 进入vi     在系统提示符号输入vi及文件名称后,就进入vi全屏幕编辑画面: $ vi file  不过有一点要特别注意,就是您进入vi之后,是处于「命令行模式(comman ...

  5. 使用Supervisord软件管理go服务进程

    一.介绍Supervisord软件1.什么是Supervisord?Supervisord是一个非常优秀的进程管理工具,使用Python开发.它可以在类UNIX系统的方式让用户来准确地监视和控制后台一 ...

  6. ASP.NET Core 配置文件

    在ASP.NET Core 中,应用程序配置数据可以使用JSON, XML 和 INI格式 和内置环境变量,命令行参数或内存中的集合. 1.如何获取和设置配置 ASP.NET Core配置系统针对以前 ...

  7. java面试经常涉及到的

    需要掌握的Java知识点: 1 基本数据类型.循环控制.String类型的使用.数组.类和对象.接口和抽象类.面向对象三大特征.异常处理.集合类(List.Map.Set) 2 能够熟练使用Sprin ...

  8. 第一阶段:Java基础 1.JAVA开发介绍---2. JVM、JRE、JDK之间的关系

    JDK :英文名称(Java Development Kit),Java 开发工具包,是针对 Java 开发员的产品.jdk 是整个 Java 开发的核心,包括了Java运行环境JRE.Java工具和 ...

  9. 【转载】C#手动往DataTable中末尾新增一行数据

    在C#中的Datatable数据变量的操作过程中,需要手动往DataTable变量的末尾新增一行数据,例如一个实际的例子,我们做数据报表,在最后一行可能需要新增一行DataRow数据作为一个汇总记录, ...

  10. IOS/Safari下document对象的scrollHeight值比Chrome更大

    之前写滚动加载更多需求时,写了这样一段错误代码 应该获取滚动列表的scrollHeight.clientHeight和scrollTop而不是整个页面的. 因为整个页面不仅包括了滚动列表,还包括了头部 ...