Python函数基础

 

前情提要

In [1]

# 字符串进阶
string1 = 'Hi, my name is Molly!'

len(string1)

string1.count('m')
string1.find('name')
# string1.index('hello')
string1.split(' ')
string1.replace(' ','_')
string1.upper()
string1.lower()
string1.capitalize()
'Hi, my name is molly!'

In [2]

# 格式化输出
name = 'Molly'
hight = 170.4
score_math = 95
score_english = 89
print('大家好!我叫%s,我的身高是%d cm, 数学成绩%d分,英语成绩%d分' % (name, hight, score_math, score_english))

print('大家好!我叫{:s},我的身高是{:d} cm, 数学成绩{:d}分,英语成绩{}分'.format(name, int(hight), score_math, score_english))

print(f"大家好!我叫{name},我的身高是{int(hight)} cm, 数学成绩{score_math}分,英语成绩{score_english}分")
大家好!我叫Molly,我的身高是170 cm, 数学成绩95分,英语成绩89分
大家好!我叫Molly,我的身高是170 cm, 数学成绩95分,英语成绩89分
大家好!我叫Molly,我的身高是170 cm, 数学成绩95分,英语成绩89分

In [3]

# 列表进阶
list1 = ['a','b','c','d','e','f']
list1.append('g') # 在末尾添加元素
list1.insert(2, 'ooo')  # 在指定位置添加元素,如果指定的下标不存在,那么就是在末尾添加

list2 = ['z','y','x']
list1.extend(list2) #合并两个list   list2中仍有元素


In [4]

list1 = ['a','b','a','d','a','f']
print(list1.count('a')) 
print(list1.index('a')) 

print(list1.pop()) 
print(list1)
list1.remove('a')
print(list1)
3
0
f
['a', 'b', 'a', 'd', 'a']
['b', 'a', 'd', 'a']

In [5]

# 列表生成式
list_1 = [1,2,3,4,5]
[n+1 for n in list_1]
[n for n in list_1 if n%2==0]
[2, 4]

函数

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

函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。

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

定义一个函数;函数调用

In [6]

def student_name(name):
    "打印学生的名字"
    print('姓名:', name)
    return {'姓名':name}

In [7]

rst = student_name('Alice')
rst 
姓名: Alice
{'姓名': 'Alice'}

In [8]

# 返回多个值
def student_name_and_age():
    "记录学生的名字和年龄"
    name = input('请输入姓名\n')
    age = int(input('请输入年龄\n'))
    print(f'姓名:{name};年龄:{age}')
    return name,age

In [9]

rst = student_name_and_age()
请输入姓名
请输入年龄
姓名:hh;年龄:22

In [10]

type(rst)
tuple

In [14]

name, age = student_name_and_age()
请输入姓名
请输入年龄
姓名:hh;年龄:5

In [15]

## 函数的嵌套调用
def worker(s):
    rst = 10 / float(s)
    return rst

def group_leader(s):
    rst = worker(s) * 2
    return rst

def CTO(s):
    return group_leader(s)

In [16]

CTO('4')
5.0

参数传递

  • 位置参数
  • 缺省参数
  • 可变参数
  • 关键字参数
  • 命名关键字参数

位置参数

位置参数是最简单的一种函数调用的方式。位置参数须以正确的顺序传入函数、数量必须和声明时的一样。

In [17]

def student_name_and_age(name, age):
    print('姓名:%s 年龄 %s' %(name, age))

In [18]

student_name_and_age('张三', 18)
姓名:张三 年龄 18

缺省参数

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

In [19]

def student_name_and_age(name, age='不愿透露'):
    "设置默认参数"
    print('姓名:%s 年龄 %s' %(name, age))

In [20]

student_name_and_age('张三')
姓名:张三 年龄 不愿透露

In [21]

# 也可以为默认参数赋值
student_name_and_age('张三', 18)
姓名:张三 年龄 18

可变参数

顾名思义,可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。

In [22]

def all_student_names(*names):
    for name in names:
        print('姓名:', name)

In [23]

all_student_names('张三','李四','王五')
姓名: 张三
姓名: 李四
姓名: 王五

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

In [24]

def all_student_names(names):
    for name in names:
        print('姓名:', name)

In [ ]

names = ('张三','李四','王五')
all_student_names(names)

关键字参数

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

In [25]

def student_info(name, age, **kw):
    print(f'我的名字叫:{name},年龄:{age},其它信息:{kw}')

In [26]

student_info('张三', 18, height=180)
我的名字叫:张三,年龄:18,其它信息:{'height': 180}

In [27]

def student_info(name, age, **kw):
    print(f'我的名字叫:{name},年龄:{age},其它信息:{kw}')
    if 'city' in kw:
        print('来自:', kw['city'])

In [28]

student_info('张三', 18, height=180, city='北京')
我的名字叫:张三,年龄:18,其它信息:{'height': 180, 'city': '北京'}
来自: 北京

In [29]

def score_info(name, yuwen, shuxue):
    print(name, '的语文成绩', yuwen)
    print(name, '的数学成绩', shuxue)

def person_info(name, age, yuwen, shuxue):
    print('姓名:', name, '年龄',age)
    score_info(name, yuwen, shuxue)    

person_info('张三', 18, 65, 60)
姓名: 张三 年龄 18
张三 的语文成绩 65
张三 的数学成绩 60

In [30]

def score_info(name, **kw):
    if '语文成绩' in kw:
        print(name, '的语文成绩', kw['语文成绩'])
    if '数学成绩' in kw:
        print(name, '的数学成绩', kw['数学成绩'])
        

def person_info(name, age, **kw):
    print('姓名:', name, '年龄',age)
    score_info(name, **kw)    

score_cfg = {'语文成绩':65, '数学成绩':60}
person_info('张三', 18, **score_cfg)
姓名: 张三 年龄 18
张三 的语文成绩 65
张三 的数学成绩 60

命名关键字参数

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

In [31]

def print_person_info(name, age, *, height, weight):
    print('我的名字叫:', name, '年龄:', age,'身高', height, '体重', weight)

In [32]

print_person_info('张三', 18, height=180, weight=75)
我的名字叫: 张三 年龄: 18 身高 180 体重 75

参数的组合

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

In [33]

def student_info(name, age=18, *books, **kw):
    print('我的名字叫:', name, '年龄:', age,'其它信息:',kw)
    if 'city' in kw:
        print('来自:', kw['city'])
    for book in books:
        print('我有',book,'书')

In [34]

student_info('张三', 18, '语文','数学','计算机', city='北京', height=180, weight=75)
我的名字叫: 张三 年龄: 18 其它信息: {'city': '北京', 'height': 180, 'weight': 75}
来自: 北京
我有 语文 书
我有 数学 书
我有 计算机 书

In [35]

def student_info(name, age=18, *books, city, **kw):
    # 如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了:
    print('我的名字叫:', name, '年龄:', age,'其它信息:',kw)
    print('来自:', city)
    for book in books:
        print('我有',book,'书')

In [36]

student_info('张三', 18, '语文','数学','计算机', city='北京', height=180, weight=75)
我的名字叫: 张三 年龄: 18 其它信息: {'height': 180, 'weight': 75}
来自: 北京
我有 语文 书
我有 数学 书
我有 计算机 书

变量的作用域和global变量

1.局部变量 作用域:在函数内

2.全局变量 作用域:在函数外

函数优先使用局部变量 在没有局部变量的情况下, 使用全局变量

In [37]

name = '张三'

def print_my_name():
    name='李四'
    print(name)
    
print_my_name()
李四

In [38]

name = '张三'

def print_my_name():
    print(name)
    
print_my_name()
张三

In [39]

# 定义在函数内部的变量,函数结束之后自动消亡
def get_my_name():
    new_name = '赵四'
get_my_name()
new_name

---------------------------------------------------------------------------NameError Traceback (most recent call last)<ipython-input-39-50225d753478> in <module> 3 new_name = '赵四' 4 get_my_name() ----> 5 new_name NameError: name 'new_name' is not defined

函数可以看作是单向玻璃 - - 不要对着车窗剔牙!  

In [40]

def change_my_name():
   print('我的名字曾经是', name)
   name = '李四'
   print('我的名字现在是', name)

In [41]

name = '张三'
change_my_name()
name

---------------------------------------------------------------------------UnboundLocalError Traceback (most recent call last)<ipython-input-41-9452ee1a9be8> in <module> 1 name = '张三' ----> 2 change_my_name() 3 name <ipython-input-40-a750cf076394> in change_my_name() 1 def change_my_name(): ----> 2 print('我的名字曾经是', name) 3 name = '李四' 4 print('我的名字现在是', name) UnboundLocalError: local variable 'name' referenced before assignment

In [ ]

def change_my_name():
    global name
    print('我的名字曾经是', name)
    name = '李四'
    print('我的名字现在是', name)

In [ ]

name = '张三'
change_my_name()
name

lambda匿名函数

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

lambda 只是一个表达式,函数体比 def 简单很多。

lambda 的主体是一个表达式,而不是一个代码块。仅仅能在 lambda 表达式中封装有限的逻辑进去。

lambda 函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。

虽然 lambda 函数看起来只能写一行,却不等同于 C 或 C++ 的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。

In [42]

# lambda 若干个输入参数 : 返回值的表达式
lambda arg1, arg2: arg1 + arg2
<function __main__.<lambda>(arg1, arg2)>

In [43]

(lambda arg1, arg2: arg1 + arg2 )(1, 2)
3

In [44]

# 加法运算 接受两个参数,返回参数之和
add = lambda arg1, arg2: arg1 + arg2
add(1,2)
3

In [ ]

# 数字转字符串
int2str = lambda x : str(x)
int2str(5)

高阶函数

In [ ]

# print本身是一个内建函数
print('hello!')

In [ ]

print

In [ ]

# 函数名其实就是指向函数的变量!
my_print = print 
my_print('a')

In [ ]

# 那么,函数的名字也可以作为一个变量,传入其它函数
def func_x(x, f):
    return f(x)

In [ ]

func_x(-1, abs)

In [ ]

# 一个函数可以接收另一个函数作为参数,这种函数就称之为高阶函数。
int2str = lambda x : str(x)
func_x(-112, int2str)

In [ ]

# 一个更复杂的例子
def func_xy(x, y ,f):
    return f(x,y)

add = lambda x,y : x+y 
mul = lambda x,y : x*y 
SS = lambda x,y : x**2 + y**2

In [ ]

print(func_xy(1,2,add))
print(func_xy(1,2,mul))
print(func_xy(1,2,SS))

map / reduce

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

In [ ]

fx = lambda x:x**2

In [ ]

ls = [1,2,3,4,5,6,7,8,9]
ms = []
for l in ls:
    ms.append(fx(l))
ms

In [ ]

rst = map(fx, ls)
list(rst)

In [ ]

map(fx, ls)

In [ ]

int2str = lambda x : str(x)
rst = map(int2str, ls)
list(rst)

reduce: 用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,依此类推,最后得到一个结果。

In [ ]

from functools import reduce
# 从python3开始,reduce函数移动到了functools这个包,每次使用前要先import

In [ ]

mul_xy = lambda x, y: x*y

In [ ]

reduce(mul_xy, [1, 3, 5, 7, 9])

sorted

排序也是在程序中经常用到的算法。无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小。如果是数字,我们可以直接比较,但如果是字符串或者两个dict呢?直接比较数学上的大小是没有意义的,因此,比较的过程必须通过函数抽象出来。

In [ ]

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

In [ ]

sorted([36, 5, -12, 9, -21], reverse=True)

In [ ]

sorted([36, 5, -12, 9, -21], key=abs)   # 按绝对值排序key指定的函数将作用于list的每一个元素上,并根据key函数返回的结果进行排序

In [ ]

list(map(abs, [36, 5, -12, 9, -21]))

In [ ]

points = [(5,2), (7,3), (3,4),(1,1),(2,6)]  # 按x坐标排序 y坐标排序 和0点距离排序

In [ ]

f_x = lambda x:x[0]
sorted(points, key=f_x)

In [ ]

f_y = lambda x:x[1]
sorted(points, key=f_y)

In [ ]

f_r = lambda x:x[0]**2+x[1]**2
sorted(points, key=f_r)

装饰器

函数作为返回值

In [ ]

def calc_sum(*args):
    ax = 0
    for n in args:
        ax = ax + n
    return ax

In [ ]

def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum

In [ ]

f = lazy_sum(1, 3, 5, 7, 9)   # 这里暂时还不想计算

In [ ]

f

In [ ]

f()

In [ ]

f1 = lazy_sum(1, 3, 5, 7, 9)
print(id(f1))
f2 = lazy_sum(1, 3, 5, 7, 9)
print(id(f2))

闭包

python中的闭包从表现形式上定义(解释)为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure).

In [ ]

def create_pointer(my_string):
    def pointer(n):
        return my_string[n]
    return pointer
    

In [ ]

pointer = create_pointer('my name is Molly')
pointer(5)

In [ ]

# 一个需要注意的问题是,返回的函数并没有立刻执行,而是直到调用了f()才执行。

def count():
    fs = []
    for i in range(1, 4):
        def f():
            # print(id(i))
            return i*i
        fs.append(f)
    return fs

f1, f2, f3 = count()

In [ ]

print(f1())
print(f2())
print(f3())

In [ ]

def count():
    def f(j):
        def g():
            # print(id(j))
            return j*j
        return g
    fs = []
    for i in range(1, 4):
        fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()
    return fs

In [ ]

f1, f2, f3 = count()
print(f1())
print(f2())
print(f3())

返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

装饰器

顾名思义,从字面意思就可以理解,它是用来"装饰"Python的工具,使得代码更具有Python简洁的风格。换句话说,它是一种函数的函数,因为装饰器传入的参数就是一个函数,然后通过实现各种功能来对这个函数的功能进行增强。

In [ ]

def worker1():
    print('我是一个勤劳的工作者!')
def worker2():
    print('我是一个勤劳的工作者!')
def worker3():
    print('我是一个勤劳的工作者!')

In [ ]

# 我现在想要打印一些日志信息
def worker1():
    print('worker1 is working...')
    print('我是一个勤劳的工作者!')

In [ ]

worker1()

In [ ]

worker1.__name__

In [ ]

# 装饰器输入一个函数,输出一个函数
def print_working(func):
    def wrapper():
        print(f'{func.__name__} is working...')
        func()
    return wrapper

In [ ]

def worker1():
    print('我是一个勤劳的工作者!')
def worker2():
    print('我是一个勤劳的工作者!')
def worker3():
    print('我是一个勤劳的工作者!')

worker1 = print_working(worker1)
worker1()
worker2= print_working(worker2)
worker2()

In [ ]

@print_working
def worker1():
    print('我是一个勤劳的工作者!')

@print_working
def worker2():
    print('我是一个勤劳的工作者!')

@print_working
def worker3():
    print('我是一个勤劳的工作者!')

In [ ]

worker1()
worker2()
worker3()

装饰器最大的优势是用于解决重复性的操作,其主要使用的场景有如下几个:

  • 计算函数运行时间
  • 给函数打日志
  • 类型检查

当然,如果遇到其他重复操作的场景也可以类比使用装饰器。

In [ ]

def arg_decorator(func):
    def wrapper(*args, **kw):
        print(f'{func.__name__} is working...')
        func(*args, **kw)
    return wrapper

In [ ]

# 带参数的装饰器
@arg_decorator
def student_info(name, age=18, *books, **kw):
    print(f'我的名字叫{name}, 今年{age}岁,我有很多本书:')
    for book in books:
        print(book)
    print(kw)

In [ ]

student_info('Molly',18, '语文书','数学书',height=170)

偏函数

通过设定参数的默认值,降低函数调用的难度

In [ ]

def student_info(name, age, city):
    print(f'我的名字叫{name}, 今年{age}岁,来自{city}')

In [ ]

student_info('Molly',18,'北京')

In [ ]

def student_info(name, age, city='北京'):
    print(f'我的名字叫{name}, 今年{age}岁,来自{city}')

In [ ]

student_info('Molly',18)

In [ ]

from functools import partial

In [ ]

def student_info(name, age, city):
    print(f'我的名字叫{name}, 今年{age}岁,来自{city}')

student_info_beijing = partial(student_info, city='北京')

In [ ]

student_info_beijing('Molly',18)

In [ ]

student_info_beijing('Molly',18, city='上海')

In [ ]

# 另一个例子
def add_xy(x,y):
    return x+y

In [ ]

add_100 = partial(add_xy, y=100)

In [ ]

add_100(10)

模块

In [ ]

import time 

In [ ]

print(time.time())
time.sleep(1)
print(time.time())

In [ ]

# 和装饰器结合
def time_decorator(func):
    def wrapper():
        time_start = time.time()
        func()
        time_end = time.time()
        print(f'程序执行了{round(time_end-time_start, 3)}秒')
    return wrapper

In [ ]

@time_decorator
def a_loop():
    for i in range(int(1e7)):
        continue

In [ ]

a_loop()

In [ ]

from functools import partial as pr 

In [ ]

# 另一个例子
def add_xy(x,y):
    return x+y

In [ ]

add_100 = partial(add_xy, y=100)

In [ ]

import numpy as np
import pandas as pd 

安装/卸载第三方模块

  • pip install / uninstall
  • conda install / uninstall

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

身在江湖的郭大侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值