day04_雷神_函数

#day04

1.函数

1.1函数传参

函数定义的时候是形参;函数执行的时候是实参

实参:

位置参数、关键字参数、混合参数

位置参数:位置一一对应

关键字参数: 可以位置不对应

混合参数:关键字参数要在位置参数之后

示例:(三元运算)
def func(a,b): return a if a > b else 666
ret = func(1,2)
print(ret)  

形参:位置参数、默认参数、动态参数

位置参数: 一一对应

默认参数:在位置参数后边,也是一个关键字的定义

动态参数: *args 函数定义的时候聚合,生成一个元祖数据;函数执行的的时候打散元祖数据,形成位置参数。

**kwargs 函数定义的时候聚合,将关键字参数聚合成一个字典数据,函数执行的时候打散这个字典数据,形成关键字参数。

def func(*args,**kwargs):
    print(args)
    print(kwargs)
func((1,2,3,4,),1,2,3,4)
结果:
((1, 2, 3, 4), 1, 2, 3, 4)
{}

func(name= ‘alex‘,age = ‘18‘)
结果:
()
{‘name‘: ‘alex‘, ‘age‘: ‘18‘}

func(**{‘name‘:‘alex‘,‘age‘:‘18‘})
结果:和上边关键字参数一样,区别是用**需要是字典格式
()
{‘name‘: ‘alex‘, ‘age‘: ‘18‘}

形参的顺序: 位置参数、*args、默认参数、**kwargs

位置参数在最开始;默认参数如果在*args的前边,就不会起作用

示例:
def f(a,b,*args,sex = ‘man‘):
    print(a,b,sex,args)
f(1,2,3,4,5,6)
结果:
1 2 man (3, 4, 5, 6)

def f(a,b,sex = ‘man‘,*args):
    print(a,b,sex,args)
f(1,2,3,4,5,6)
结果:
1 2 3 (4, 5, 6)

**kwargs就是接受的实参中的关键字参数,如果在默认参数前边,默认参数就接收不到,直接报错。

正确示例:
def func2(a,b,*args,sex=‘man‘,**kwargs):
print(a,b)
print(sex)
print(args)
print(kwargs)

func2(1,2,3,55,66,age=12,sex=‘女‘,name=‘alex‘)
结果:
1 2
女
(3, 55, 66)
{‘age‘: 12, ‘name‘: ‘alex‘}  kwargs会跳过默认参数,接受剩下的关键字参数

1.2 函数名的应用

  • 1.打印函数名
  • 函数名表示函数的内存地址

    print(func1) function func1 at 0x000000000258F9D8>

  • 2.可以作容器类数据的元素
  • 示例:

    def func1():

    print(111)

    def func2():

    print(222)

    def func3():

    print(333)

    l1 = [func1, func2, func3]

    for i in l1:

    i()

  • 3.可以作为函数的参数
  • 4.可以作为函数的返回值
  • def func1():

    return 111

    def func2(x): # x = func1

    print(222)

    return x

    ret = func2(func1) # func1作为这个函数执行体得返回值,赋值给ret,ret()表示执行

    print(ret())

    print(ret)

    结果:

    222

    111

    <function func1 at 0x000001B4D91D1E18>

    像这样得函数名,又叫第一类对象。

1.3闭包

内层函数对外层函数非全局变量得引用,就叫做闭包。

可以通过: 函数.__closure__来判断是不是闭包

示例:
name = ‘alex‘
def  func1(x):  (相当于x = name,后边引用得是变量x)
    def inner():
        print(x)
    inner()
print(inner.__closure__)  在inner()之后print。
func1(name)

结果:
返回None不是闭包,一个带cell值得东西就是闭包。
alex
(<cell at 0x0000023CC8CC6588: str object at 0x0000023CC8C8B340>,)

又一个机制:闭包得内容会留在内存中,不会随着函数得结束而释放,一段时间不用才会清空,可以在爬虫用。正常得函数,函数结束之后,他得临时名称空间就会结束。

示例:
from urllib.request import urlopen

def index():
    url = "http://www.xiaohua100.cn/index.html"
    def get():
        return urlopen(url).read()
    return get

xiaohua = index()  # get
content = xiaohua()
content1 = xiaohua()
content2 = xiaohua()   这个内容可以反复使用
print(content.decode())  默认解码是utf-8的方式,等于content.decode(‘utf-8‘)

编码

a = "中国"
a1 = a.encode("utf-8")  """ encode是字符串改变为byte字节数据类型,byte类型用utf-得编码,字符串之前是unicode得编码"""
print(a1,type(a1),type(a))

结果:
b‘\xe4\xb8\xad\xe5\x9b\xbd‘ <class ‘bytes‘> <class ‘str‘>

1.4 装饰器

经典装饰器

def wrapper(f):  """在这里相当于f = func1"""
    def inner():
        """ 函数执行之前的操作"""
        ret = f()
        """ 函数执行之后的操作"""
        return ret """把执行函数得返回值返回给inner(),即已经改了名字得func1()"""
    return inner

@wrapper
def func1():  """在这里相当于执行func1 = wrapper(func1)"""
    print("111")
    return OK

print(func1()) print,打印出上边得返回值ret。

2. 名称空间、作用域、取值顺序

名称空间

名称空间分为: 内置名称空间、全局名称空间、局部名称空间

加载顺序: 打开程序,首先加载内置名称空间,程序执行,一行一行读代码,

先加载全局名称空间,遇到函数,在把函数加载到内存里,此时不关心函数体,遇到函数执行者,才开始加载

函数中的变量只能在函数内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。

作用域

全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效

局部作用域:局部名称空间,只能在局部范围内生效

取值顺序:

单向不可逆,从在找寻变量时,从小范围,一层一层到大范围去找寻。

 在局部调用:局部命名空间->全局命名空间->内置命名空间

 在全局调用:全局命名空间->内置命名空间

3. 内置函数 globals()、locals()

globals()

返回一个字典,字典里面的内容是全局作用域的内容。

locals()

返回一个字典,当前位置 的所有变量。

示例:
def func1():
    name1 = ‘oldboy‘
    age = 10000
    print(locals())  #这是当前位置
    def func2():
        name2 = ‘wusir‘
        age2 = 25
        print(globals())
        print(locals())   #只能返回name2,这是当前位置。
    func2()
func1()

4. 关键字 global、nonlocal

global

  1. 引用并且改变一个全局变量
  2. 在局部作用域声明一个全局变量
示例:
count = 1
def func1():
    global count
    count = count + 1
    count = count + 100
    print(count)
func1()
print(count)
print(globals())

def func1():
    global name
    name = ‘alex‘
    print(name)
func1()
print(name)

nonlocal

1, 不能操作全局变量

  1. 在哪一层引用得,就从该层开始全部改变。
示例:
def func1():
    count = 1
    def inner():   """ inner开始引用nonlocal,后边得层都开始改变了"""
        nonlocal count
        count = count + 3
        # print(count)
        # def inner2():
        #    pass
    inner()
    print(count)
func1()

# 取值:引用而不是改变
# 取值是从小到大取值 LEGB
# 想改变上层空间的变量 要用到global nonlocal

对于可变得数据类型,list、dic、set等,要改变他们,不需要global、nonlocal。

函数里得默认参数如果是一个可变数据类型,它在内存里得位置永远是一个。

示例:
def extendList(val,list=[]):
    list.append(val)
    return list
list1 = extendList(10)
print(‘list1=%s‘%list1)  # [10,]
list2 = extendList(123,[])
print(‘list2=%s‘%list2)  # [123,]
list3 = extendList(‘a‘)
print(‘list3=%s‘%list3)  #[10,‘a‘]

print(‘list1=%s‘%list1)
print(‘list2=%s‘%list2)
print(‘list3=%s‘%list3)

练习题

1.函数,检查获取传入列表或元组对象的所有奇数位索引 0 1 2 3对应的元素,并将其作为新列表返回给调用者。

dic = [1,2,3,4,5,6]
def check():
    dic1 = dic[1::2]
    return dic1
print(check())
  1. 写函数,判断用户传入的对象(字符串、列表、元组)长度是否大于5。大于退出,小于继续输入。
示例:
flag = True
while flag:
    a = input("input:")
    def func():
        global flag
        b = len(a)
        print(b,type(b))  #8 <class ‘int‘>
        if b > 5:
            print("长度大于5!")
            flag = False
        else:
            pass
    func()
  1. 写函数,检查传入列表的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。
li = [1,2,3,4,5,6]
def check():
    if len(li) > 2:
        li1 = li[:2]  #字符串切片[起始索引:结束索引+1:步长],顾首不顾尾,所以结束索引+1
        print(li1)
check()
  1. 写函数,计算传入字符串中【数字】、【字母】、【空格] 以及 【其他】的个数,并返回结果。
def str_number(str_num):
    count = 0
    count2 = 0
    count3 = 0
    count4 = 0
    for i in str_num:
        if i.isdigit() == True:
            count += 1
        elif i.isalpha() == True:
            count2 += 1
        elif i.isspace() == True:
            count3 += 1
        else:
            count4 += 1
    print("数字有%d个"%count)
    print("字母有%d个"%count2)
    print("空隔有%d个" % count3)
    print("其它有%d个" % count4)
    # return

str_num = input("输入:")
str_number(str_num)

写函数,检查传入字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。

dic = {"k1": "v1v1", "k2": [11,22,33,44]}

PS:字典中的value只能是字符串或列表

def a4(arg):
    ret = {}
    for key,value in arg.items():
        if len(value) > 2:
            ret[key] = value[0:2]
        else:
            ret[key] = value
    return  ret

dic = {"k1": "v1v1", "k2": [11, 22, 33, 44],"k3":"12"}
r = a4(dic)
print(r)

练习:

li = [1,2,3,4,5,6]
def func1(*args):
    print(args)
func1(li)
结果:
([1, 2, 3, 4, 5, 6],)    列表可以这样

dic = {"k1": "v1v1", "k2": [11, 22, 33, 44],"k3":"12"}
def func1(f):
    for k,v in dic.items():  直接f代表了传入的字典。
        print(k,v)
func1(dic)
结果:
k1 v1v1
k2 [11, 22, 33, 44]
k3 12

dic = {"k1": "v1v1", "k2": [11, 22, 33, 44],"k3":"12"}
def func1(**kwargs):
    print(kwargs)
# func1(dic)    #报错func1() takes 0 positional arguments but 1 was given
# func1()  #返回{}
func1(k1= "v1v1")  #返回{‘k1‘: ‘v1v1‘}   字典用**kwargs必须使用关键字参数,要具体化。

原文地址:https://www.cnblogs.com/houbinglei/p/9268808.html

时间: 2024-11-13 04:30:19

day04_雷神_函数的相关文章

day05_雷神_函数进阶

#day05 1.迭代器 1.1可迭代对象 str,list,tuple,dict,set,range,文件句柄 等都是可迭代对象 第一种方法:在该对象中,含有__iter__方法的就是可迭代对象,遵循可迭代协议. print(dir(str)) dir() 打印出str对象的所有方法. print('__iter__' in dir(list)) 返回值: True 说明是可迭代对象 第二种方法: isinstance("123",Iterable) from collections

[Java]_函数传参的疑惑与思考

问题来源于leetcode上的两道题 Path Sum I && II,分别写了两个dfs. 1 void dfs(TreeNode node , int sum , ArrayList<Integer> curPath) 2 void dfs(TreeNode node , int sum , boolean ifExist) 问题:在1号中我可以在方法中修改curPath,在结束函数调用时,变量修改仍然生效.   在2号问题中,我即使在函数中修改了ifExist,结束函数调

python_字符_函数

一.字符集和字符编码 1.定义 计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的英文.汉字等字符是二进制数转换之后的结果.通俗的说,按照何种规则将字符存储在计算机中,如'a'用什么表示,称为"编码":反之,将存储在计算机中的二进制数解析显示出来,称为"解码",如同密码学中的加密和解密.在解码过程中,如果使用了错误的解码规则,则导致'a'解析成'b'或者乱码. 字符(Character):是一个信息单位,在计算机里面,一个中文汉字是一个字符,一个英文字母是

DayDayUP_Python自学记录[6]_函数学习

Python 函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也可以自己创建函数,这被叫做用户自定义函数. 定义一个函数 你可以定义一个由自己想要功能的函数,以下是简单的规则: 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号(). 任何传入参数和自变量必须放在圆括号中间.圆括号之间可以用于定义参数. 函数的第一行语句可以选择性地使用文档字符串-用于

python入门第十一天_函数

Python 函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 不同于数学中的函数定义,在计算机中,函数又可以称呼为子程序. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也可以自己创建函数,这被叫做用户自定义函数. 定义一个函数 你可以定义一个由自己想要功能的函数,以下是简单的规则: 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号(). 任何传入参数和自变量必须放在圆括号中间.圆括号之间可以用

day07_雷神_面向对象进阶

day07 1.接口类(抽象类) 接口类和抽象类是一种规范,写代码时的规范. 两个思想: 一个是统一接口,一个是定义规则. 最终版本:接口类,抽象类,是一种规范,写代码时的规范 强制性的规定. from abc import ABCMeta,abstractmethod class Payrole(metaclass=ABCMeta): # 抽象类或者接口类,制定规范,统一方法名. @abstractmethod def pay(self): pass class QQpay(Payrole):

select语句_函数

1.1 查询语句 1.1.1 select select 用于从数据看查询数据.语法: select field1,filed2,.. . from tablename [where condition] 1 select ename "姓名",job "岗位" from emp; 表的别名: 1 select emp.ename,emp.job from emp; 2 select e.ename,e.job from emp e; * 通配符表示查询所有字段.如

js基础知识之_函数

javascript函数 函数概念 将完成某一特定功能的代码集合起来,可以重复使用 白话函数理解-函数就是一个工厂,帮大家实现某一个功能 优点 -时程序更加简洁 -逻辑更有条例 -调用方便 -维护更加容易 函数的声明方式(创建) 1.基本语法 function 关键字 function 函数名([参数1],[参数2]....){ 函数体 [return]//返回值 } 2.字面量定义的形式(匿名函数) var 变量=function()([参数1],[参数2]....){ 函数体 [return

Python基础(6)_函数

一 为何要有函数? 不加区分地将所有功能的代码垒到一起,问题是: 代码可读性差 代码冗余 代码可扩展差 如何解决? 函数即工具,事先准备工具的过程是定义函数,拿来就用指的就是函数调用 结论:函数使用必须是:先定义,后调用 python中函数定义方法: def test(x): "The function definitions" x+=1 return x def:定义函数的关键字 test:函数名 ():内可定义形参 "":文档描述(非必要,但是强烈建议为你的函数