关于函数的默认值与python闭包以及迭代器

# 在函数中如果默认值参数是一个可变的数据类型, 如果有人调用的时候改变了他. 其他位置看到的也跟着改变了
def fn(val,list=[]):
    list.append(val)
    return list

print(fn(5))
# 这个位置我们给val传值了打印的结果一定是[5]

print(fn(6))

# 这个位置我们继续传值发现结果是[5, 6],那么也就是说函数中参数的默认值是同一个,而不是每次调用函数生产新的默认值
# # 在函数中如果默认值参数是一个可变的数据类型, 如果有人调用的时候改变了他. 其他位置看到的也跟着改变了
# def fn(val,list=[]):
#     list.append(val)
#     return list
#
# print(fn(5))
# # 这个位置我们给val传值了打印的结果一定是[5]
#
# print(fn(6))

# 这个位置我们继续传值发现结果是[5, 6],那么也就是说函数中参数的默认值是同一个,而不是每次调用函数生产新的默认值

# 什么是闭包以及闭包实际作用
# 我们知道函数声明的时候是不执行的,只有在调用的时候才会在内存开辟空间,python内部的垃圾回收机制,会在函数执行完毕后回收这块内存

def fn1():
    val = 100
    print(val)
fn1()
# 这个时候在执行完fn1后,它所在的那块内存就会被清空,而闭包的作用就是可以让这块内存常驻

def fn2():
    val  = 100
    def fn3():
        return val
    print(fn1.__closure__)
    print(fn2.__closure__)
    print(fn3.__closure__)
    return fn3
print(fn2()())

# 可以用__closure__函数来检测是不是闭包
# None
# None
# (<cell at 0x000001366E928B28: int object at 0x00007FFAD5407D60>,) fn3的结果是闭包

# 在python中srt,list,tuple,dict,set,file这些都属于可迭代对象,那么他们为什么是可迭代对象呢,因为它们遵循了可迭代协议

s = "真相定论"
# print(dir(s))
# [‘__add__‘, ‘__class__‘, ‘__contains__‘, ‘__delattr__‘, ‘__dir__‘, ‘__doc__‘, ‘__eq__‘, ‘__format__‘, ‘__ge__‘, ‘__getattribute__‘, ‘__getitem__‘,
#  ‘__getnewargs__‘, ‘__gt__‘, ‘__hash__‘, ‘__init__‘, ‘__init_subclass__‘, ‘__iter__‘, ‘__le__‘, ‘__len__‘, ‘__lt__‘, ‘__mod__‘, ‘__mul__‘, ‘__ne__‘,
#  ‘__new__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__rmod__‘, ‘__rmul__‘, ‘__setattr__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, ‘capitalize‘,
#  ‘casefold‘, ‘center‘, ‘count‘, ‘encode‘, ‘endswith‘, ‘expandtabs‘, ‘find‘, ‘format‘, ‘format_map‘, ‘index‘, ‘isalnum‘, ‘isalpha‘, ‘isascii‘, ‘isdecimal‘,
#  ‘isdigit‘, ‘isidentifier‘, ‘islower‘, ‘isnumeric‘, ‘isprintable‘, ‘isspace‘, ‘istitle‘, ‘isupper‘, ‘join‘, ‘ljust‘, ‘lower‘, ‘lstrip‘, ‘maketrans‘, ‘partition‘,
#  ‘replace‘, ‘rfind‘, ‘rindex‘, ‘rjust‘, ‘rpartition‘, ‘rsplit‘, ‘rstrip‘, ‘split‘, ‘splitlines‘, ‘startswith‘, ‘strip‘, ‘swapcase‘, ‘title‘, ‘translate‘, ‘upper‘,
#  ‘zfill‘]

# 我们发现字符串中有__iter__这个就是迭代器,而拥有迭代器的则是可迭代对象`

# print(dir(s.__iter__()))
# [‘__class__‘, ‘__delattr__‘, ‘__dir__‘, ‘__doc__‘, ‘__eq__‘, ‘__format__‘, ‘__ge__‘, ‘__getattribute__‘, ‘__gt__‘, ‘__hash__‘, ‘__init__‘, ‘__init_subclass__‘,
#  ‘__iter__‘, ‘__le__‘, ‘__length_hint__‘, ‘__lt__‘, ‘__ne__‘, ‘__new__‘, ‘__next__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__setattr__‘, ‘__setstate__‘,
#  ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘]
# 当我们执行它获取迭代器时,发现迭代器中也含有iter也是可迭代对象

itr = s.__iter__()
# 获取迭代器
print(itr.__next__())
print(itr.__next__())
print(itr.__next__())
print(itr.__next__())
# 真
# # 相
# # 定
# # 论
#  分别打印出了四个字

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

itr2 = lst.__iter__()

print(itr2.__next__())
print(itr2.__next__())
print(itr2.__next__())
print(itr2.__next__())
print(itr2.__next__())

# 获取lst的迭代器并且利用nextAPI实现了手动迭代
# 用while模拟一下迭代器
while 1:
    try:
        name = itr2.__next__()
        print(name)
    except StopIteration:
        break
# try跟js中的容错机制差不多

# 还用一种判断是否为迭代器的方法
from collections.abc import Iterable
from collections.abc import Iterator

print(isinstance(itr,Iterable))
print(isinstance(itr,Iterator))

# True
# True
# 两个True所以itr即是迭代器又是可迭代对象

print(isinstance(lst,Iterable))
print(isinstance(lst,Iterator))

# lst是可迭代对象但不是迭代器

原文地址:https://www.cnblogs.com/tengx/p/11671036.html

时间: 2024-11-09 23:09:03

关于函数的默认值与python闭包以及迭代器的相关文章

Python函数参数默认值的陷阱和原理深究(转)

add by zhj: 在Python文档中清楚的说明了默认参数是怎么工作的,如下 "Default parameter values are evaluated when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that the same “pre-computed” value is used

C# 函数参数默认值

namespace 函数参数默认值 { class Program { public static void Test(int i =100) { Console.WriteLine("{0}",i); } static void Main(string[] args) { Test(); Test(222); Console.Read(); } } } 输出:100 222

java函数参数默认值

java通过函数的重载来实现函数参数默认值 public class ParameterDefault { /** * @param args */ public String getName(String givenName,String familyName){ return givenName+"."+familyName; } public String getName(String givenName){ return getName(givenName,"Xie&

C++函数带默认值的几种情形

1. 默认参数的规则 默认值定义 C++支持函数参数带默认值.这里所谓的默认值,指的是在调用函数时,可以不指定某些参数,编译器会自动把默认值传递到函数调用中. 默认值位置 指定默认值的参数必须位于形参列表最右端,从右往左.否则会出现二义性,编译器无法处理. 默认值设置 默认值可以在函数声明或函数定义中设置,只要保证不出现参数重定义即可. 2.默认参数示例 在函数声明中设置默认值 这是最常见的一种情形.主要有以下两种声明方式: 声明中给参数赋默认值 声明中用类型指定默认值 float area(f

ES6函数参数默认值作用域的模拟原理实现与个人的一些推测

一.函数参数默认值中模糊的独立作用域 我在ES6入门学习函数拓展这一篇博客中有记录,当函数的参数使用默认值时,参数会在初始化过程中产生一个独立的作用域,初始化完成作用域会消失:如果不使用参数默认值,不会产生这个作用域:产生疑问是因为这段代码: var x = 1; function foo(x, y = function () {x = 2;}) { var x = 3; y(); console.log(x); }; foo();//3 foo(4);//3 console.log(x);//

【函数】plsql 函数的默认值

1.创建函数 1 CREATE OR REPLACE FUNCTION fk_url_format(url VARCHAR2,charset VARCHAR2 :='UTF-8')RETURN VARCHAR2 2 IS 3 BEGIN 4 dbms_output.put_line(charset); 5 RETURN utl_url.escape(url,TRUE,charset); 6 END;--使用DEFAULT也可以:CREATE OR REPLACE FUNCTION fk_url_

C++基础2 引用 函数扩展: 默认值 占位符 指针 重载 类:引用类指针 声明实现分开写

[难点]指针引用 [email protected]:~/c++$ cat main.cpp  #include <stdlib.h> #include "iostream" using namespace std; int a = 20; struct Teacher { int age; char name[64]; }; int fun1(struct Teacher ** p) { int ret = 0; if(p == NULL) { ret = -1; ret

js设置函数参数默认值的3种方法

js默认是不支持funtion f($a=a){}这种写法的,如果想设置函数参数的默认值,可以参考如下三种方法: 第一种方法: 使用arguments,函数所有的参数都会存入arguments数组离去,所以我们可以从中获取相应的参数然后赋值 function example(a,b){ var a = arguments[0] ? arguments[0] : 1;//设置参数a的默认值为1 var b = arguments[1] ? arguments[1] : 2;//设置参数b的默认值为

ES6---函数的扩展之函数的默认值

1.函数默认值 function add(a,b=3){ return a+b; } add(1,2);//3 add(1);//4 理解起来也很简单,就是在函数定义的时候设置一个默认值,当调用函数没有传参时,可以根据默认值为其匹配一个参数值 这样子的好处嘛,可以避免在调用时没有传参导致函数报错,同时对于阅读代码也更加直观了,代码量也更少了,嘻嘻 直观是因为我们只需要看函数就知道该参数是否可选 代码更少是因为在ES6以前,函数不能设置默认值,如果在调用的时候没有传参进去, 那么需要进行是否传递该