谈谈自己的理解:python中闭包,闭包的实质.

Python77

如果在一个函数的内部定义了另一个函数,外部的我们叫他外函数,内部的我们叫他内函数。

闭包:

在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。

一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。

很晦涩很难理解啊!!我们来看一段代码

从上面例子是我写的一个最简单的很典型的闭包。我估计如果是初学的小伙伴,可能很多名词都不明白是什么意思,没关系,我把这些名词按照自己的理解去解释一下~

1 外函数返回了内函数的引用:

引用是什么?

在python中一切都是对象,包括整型数据1,函数,其实是对象。

当我们进行a=1的时候,实际上在内存当中有一个地方存了值1,然后用a这个变量名存了1所在内存位置的引用。引用就好像c语言里的指针,大家可以把引用理解成地址。a只不过是一个变量名字,a里面存的是1这个数值所在的地址,就是a里面存了数值1的引用。

相同的道理,当我们在python中定义一个函数def demo(): 的时候,内存当中会开辟一些空间,存下这个函数的代码、内部的局部变量等等。这个demo只不过是一个变量名字,它里面存了这个函数所在位置的引用而已。我们还可以进行x = demo, y = demo, 这样的操作就相当于,把demo里存的东西赋值给x和y,这样x 和y 都指向了demo函数所在的引用,在这之后我们可以用x() 或者 y() 来调用我们自己创建的demo() ,调用的实际上根本就是一个函数,x、y和demo三个变量名存了同一个函数的引用。

不知道大家有没有理解,很晦涩,希望我说明白了我想表达的。

有了上面的解释,我们可以继续说,返回内函数的引用是怎么回事了。对于闭包,在外函数outer中 最后return inner,我们在调用外函数 demo = outer() 的时候,outer返回了inner,inner是一个函数的引用,这个引用被存入了demo中。所以接下来我们再进行demo() 的时候,相当于运行了inner函数。

同时我们发现,一个函数,如果函数名后紧跟一对括号,相当于现在我就要调用这个函数,如果不跟括号,相当于只是一个函数的名字,里面存了函数所在位置的引用。

2 外函数把临时变量绑定给内函数:

按照我们正常的认知,一个函数结束的时候,会把自己的临时变量都释放还给内存,之后变量都不存在了。一般情况下,确实是这样的。但是闭包是一个特别的情况。外部函数发现,自己的临时变量会在将来的内部函数中用到,自己在结束的时候,返回内函数的同时,会把外函数的临时变量送给内函数绑定在一起。所以外函数已经结束了,调用内函数的时候仍然能够使用外函数的临时变量。

在我编写的实例中,我两次调用外部函数outer,分别传入的值是5和7。内部函数只定义了一次,我们发现调用的时候,内部函数是能识别外函数的临时变量是不一样的。python中一切都是对象,虽然函数我们只定义了一次,但是外函数在运行的时候,实际上是按照里面代码执行的,外函数里创建了一个函数,我们每次调用外函数,它都创建一个内函数,虽然代码一样,但是却创建了不同的对象,并且把每次传入的临时变量数值绑定给内函数,再把内函数引用返回。虽然内函数代码是一样的,但其实,我们每次调用外函数,都返回不同的实例对象的引用,他们的功能是一样的,但是它们实际上不是同一个函数对象。

3. 闭包中内函数修改外函数局部变量

在闭包内函数中,我们可以随意使用外函数绑定来的临时变量,但是如果我们想修改外函数临时变量数值的时候发现出问题了!咋回事捏??!!

在基本的python语法当中,一个函数可以随意读取全局数据,但是要修改全局数据的时候有两种方法:

1 . global 声明全局变量
2 全局变量是可变类型数据的时候可以修改

在闭包内函数也是类似的情况。在内函数中想修改闭包变量(外函数绑定给内函数的局部变量)的时候:

  1. 在python3中,可以用nonlocal 关键字声明 一个变量, 表示这个变量不是局部变量空间的变量,需要向上一层变量空间找这个变量。
  2. 在python2中,没有nonlocal这个关键字,我们可以把闭包变量改成可变类型数据进行修改,比如列表。

上代码!!!

从上面代码中我们能看出来,在内函数中,分别对闭包变量进行了修改,打印出来的结果也确实是修改之后的结果。以上两种方法就是内函数修改闭包变量的方法。

还有一点需要注意:使用闭包的过程中,一旦外函数被调用一次返回了内函数的引用,虽然每次调用内函数,是开启一个函数执行过后消亡,但是闭包变量实际上只有一份,每次开启内函数都在使用同一份闭包变量

上代码!

两次分别打印出11和14,由此可见,每次调用inner的时候,使用的闭包变量x实际上是同一个。

闭包有啥用??!!

很多伙伴很糊涂,闭包有啥用啊??还这么难懂!

  1. 装饰器!!!装饰器是做什么的??其中一个应用就是,我们工作中写了一个登录功能,我们想统计这个功能执行花了多长时间,我们可以用装饰器装饰这个登录模块,装饰器帮我们完成登录函数执行之前和之后取时间。

  2. 面向对象!!!经历了上面的分析,我们发现外函数的临时变量送给了内函数。大家回想一下类对象的情况,对象有好多类似的属性和方法,所以我们创建类,用类创建出来的对象都具有相同的属性方法。闭包也是实现面向对象的方法之一。在python当中虽然我们不这样用,在其他编程语言入比如avaScript中,经常用闭包来实现面向对象编程

  3. 实现单例模式!!! 其实这也是装饰器的应用。单例模式毕竟比较高大,需要有一定项目经验才能理解单利模式到底是干啥用的,我们就不探讨了。

Original: https://blog.51cto.com/u_15722381/5483119
Author: ch3nnn
Title: 谈谈自己的理解:python中闭包,闭包的实质.



相关阅读1

Title: 使用 Tkinter 和 Python 制作文本编辑器

谈谈自己的理解:python中闭包,闭包的实质.

在这篇教程中,我们使用 Tkinter 和 Python 在线运行并制作一个可以新建、打开、编辑并保存文本的 文本编辑器应用。

我们可以把这个简易的文本编辑器拆分成三个部分:

  1. 打开或编辑文件的​ ​btn_open​​ 按钮
  2. 保存文件的​ ​btn_save​​ 按钮
  3. 编写或编辑文件文本的​ ​txt_edit​​ 输入框

在我们用 Tkinter 绘制的 GUI 中,我们会把两个按钮集中在输入框的左手边,整个应用窗口大约为 800 像素,同时我们也会设置输入框跟随应用窗口大小进行调整。我们的编辑器大概长这样:

谈谈自己的理解:python中闭包,闭包的实质.

使用 Python 在线运行项目源代码:​https://3921d9436a-share.lightly.teamcode.com ​

绘制应用基础轮廓

基本上,我们的文本编辑器包含一行两列,比 较窄的那一列为按钮,而比 较宽的那一列为文本框。我们可以通过 ​ ​.grid()​​​ 函数来调整大小。同时,我们也可以在 ​ ​.rowconfigure()​​​ 以及 ​ ​.columnconfigure()​​​ 中,把应用窗口和文本框的 ​ ​minsize​​​ 设置为 800,然后将这两个参数的 ​ ​weight​​ 设置为 1。

为了让两个按钮都安分地待在同一列,我们需要创建一个名为 ​ ​frm_buttons​​​ 的框架,然后把 ​ ​btn_open​​​ 的新建、编辑按钮放在上层,​ ​btn_save​​ 按钮放在下层。

import tkinter as tkwindow = tk.Tk()window.title("Text Editor")window.rowconfigure(0, minsize=800, weight=1)window.columnconfigure(1, minsize=800, weight=1) txt_edit = tk.Text(window)frm_buttons = tk.Frame(window, relief=tk.RAISED, bd=2)btn_open = tk.Button(frm_buttons, text="Open")btn_save = tk.Button(frm_buttons, text="Save As...")
  • 第 1 行导入​ ​tkinter​
  • 第 3、4 创建名为​ ​"文本编辑器"​​ 的新窗口
  • 第 6、7 行设置窗口行列参数
  • 第 9-12 行创建文本框、按钮框架以及两个所需的按钮。

设置按钮

基本设置完成后,我们可以使用 ​ ​.grid()​​ 函数为两个按钮进行设置:

btn_open.grid(row=0, column=0, sticky="ew", padx=5, pady=5)btn_save.grid(row=1, column=0, sticky="ew", padx=5)

这两行简单的代码会在按钮框架中创建一个两行一列的网格,而我们为 ​ ​btn_open​​​ 及 ​ ​btn_save​​​ 两个按钮的 ​ ​sticky​​​ 参数设置为 ​ ​"ew"​​,强制这两个按钮 横向填满整个框,以确保按钮的大小相同。然后,我们也通过 ​ ​padx​​​ 和 ​ ​pady​​ 为两个按钮之间添加一点间距,以至于按钮之间不会太拥挤。

按钮的框架完成后,我们同样调整一下窗口中的其他元素:

frm_buttons.grid(row=0, column=0, sticky="ns")txt_edit.grid(row=0, column=1, sticky="nsew")

这两行代码和上一段相似,但这时在窗口中创建一个一行两列的网格。我们把 ​ ​frm_buttons​​​ 写在 ​ ​txt_edit​​ 上方,那样展示的效果就会是按钮在左,文本框在右。

我们把按钮列的 ​ ​sticky​​​ 参数设置为 ​ ​"ns"​​,让按钮列 竖向填满,而文本框的 ​ ​sticky​​​ 参数设置为 ​ ​"nsew"​​,让它 填满四周

基本框架完成后,我们可以在项目下方添加 ​ ​window.mainloop()​​​ 函数并使用 Python 在线运行代码。窗口基本上应该在这样:

谈谈自己的理解:python中闭包,闭包的实质.

添加打开按钮功能

我们的文本编辑器现在已经有模有样了,但我们还需要为按钮添加相应的指令。我们需要让 ​ ​btn_open​​​ 具有打开文件对话的功能,让用户打开文件后将文本展示在 ​ ​txt_edit​​ 的文本框中。

import tkinter as tk 3def open_file():"""Open a file for editing."""    filepath = askopenfilename(        filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")]    )    if not filepath:        return    txt_edit.delete("1.0", tk.END)    with open(filepath, mode="r", encoding="utf-8") as input_file:        text = input_file.read()        txt_edit.insert(tk.END, text)    window.title(f"Simple Text Editor - {filepath}")
  • 第 5 - 7 行使用​ ​tkinter.filedialog​​​ 模块中的​ ​askopenfilename()​​​ 对话来打开文件对话框,然后将路径保存到​ ​filepath​​ 中。
  • 第 8、9 检查用户是否关闭对话框或选择取消,如是则​ ​filepath​​​ 为​ ​None​​。
  • 第 10 行使用​ ​.delete()​​ 命令清楚文本框中现有的内容。
  • 第 11、12 行打开并使用​ ​.read()​​ 读取相关内容并把文本保存为字符串。
  • 第 13 行使用​ ​.insert()​​ 将字符串插入文本框。
  • 第 14 行修改窗口的标题,让窗口标题包含文件名称。

这些步骤完成后,我们还需要在项目头部添加 ​ ​import askopenfilename() from tkinter.filedialog​​​,然后把 ​ ​btn_opn​​​ 的 ​ ​command​​​ 参数设置为 ​ ​open_file​​:

import tkinter as tkfrom tkinter.filedialog import askopenfilenamedef open_file():    """Open a file for editing."""    filepath = askopenfilename(        filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")]    )    if not filepath:        return    txt_edit.delete("1.0", tk.END)    with open(filepath, mode="r", encoding="utf-8") as input_file:        text = input_file.read()        txt_edit.insert(tk.END, text)    window.title(f"Simple Text Editor - {filepath}")window = tk.Tk()window.title("Simple Text Editor")window.rowconfigure(0, minsize=800, weight=1)window.columnconfigure(1, minsize=800, weight=1)txt_edit = tk.Text(window)frm_buttons = tk.Frame(window, relief=tk.RAISED, bd=2)btn_open = tk.Button(frm_buttons, text="Open", command=open_file)btn_save = tk.Button(frm_buttons, text="Save As...")

添加保存按钮功能

打开按钮完成后,我们还需要为保存按钮添加相应的功能。我们需要让 ​ ​btn_save​​​ 打开保存文件对话框,通过 ​ ​tkinter.filedialog​​​ 模块中的 ​ ​asksaveasfilename()​​ 功能,提取文本框中的文本并写入相应的路径。

def save_file():    """Save the current file as a new file."""    filepath = asksaveasfilename(        defaultextension=".txt",        filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")],    )    if not filepath:        return    with open(filepath, mode="w", encoding="utf-8") as output_file:        text = txt_edit.get("1.0", tk.END)        output_file.write(text)    window.title(f"Simple Text Editor - {filepath}")

这个保存按钮的步骤基本上与打开按钮的步骤相似,其中:

  • 第 25 行在所选路径创建一个新的文件。
  • 第 26 行从文本框中通过​ ​.get()​​​ 提取字符串并存入​ ​text​​ 变量中。
  • 第 27 把​ ​text​​ 写入文件。

这部分完成后,同样需要在项目头部文件导入 ​ ​asksaveasfilename()​​:

import tkinter as tkfrom tkinter.filedialog import askopenfilename, asksaveasfilename

最后,把 ​ ​btn_save​​​ 的 ​ ​command​​​ 参数调整为 ​ ​save_file​​ 即大功告成!

使用 Python 在线运行项目源代码:​https://3921d9436a-share.lightly.teamcode.com ​

Original: https://blog.51cto.com/u_15340774/5504991
Author: TeamCode
Title: 使用 Tkinter 和 Python 制作文本编辑器

相关阅读2

Title: 利用Python发现60%以上女孩的罩杯是B,但A穿衣却是百搭且很高级

​最近常听到说女生的A罩杯,穿衣百搭且很高级!

今天,我们就爬取京东商城某文胸品牌不同size的大致销售情况,来看看当前什么 尺码才是主流吧!

目录

  1. 需求梳理

  2. 数据采集

  3. 统计展示

3.1. cup分布

3.2. color分布

  1. 就这样吧

  2. Python学习资源

  1. 需求梳理

```python;gutter:true;
很多人学习蟒蛇,不知道从何学起。

很多人学习寻找python,掌握了基本语法之后,不知道在哪里案例上手。

很多已经可能知道案例的人,却不怎么去学习更多高深的知识。

这三类人,我给大家提供一个好的学习平台,免费获取视频教程,电子书,以及课程的源代码!

QQ群:101677771

欢迎加入,一起讨论学习


本文比较简单,单纯对京东评论数最多的某文胸品牌不同size的商品评论数进行采集,然后统计出不同size的 **占比**。

由于京东没有类似销量(或多少人付款)等数据,我们这里仅用评论数做对比维度。关于评论数的获取,我们这里就不展开介绍了。

通过在京东进行商品类型选择内衣-文胸-适用人群 青年,再按照评论数排序,我们可以得到排名靠前的商品列表。由于前2个都是均码无尺寸的,第3个是文胸洗衣袋(也是均码无尺寸),故而我们选择了第4个商品。

​

寻找目标品牌

然后,我们直接点击进入到第4个商品的详情页面,发现存在很多7种颜色和10种尺寸,这组合有点多啊。

为了更好的获取每件商品的评论数据,我们这里需要先获取每个商品的productId。于是,我们F12进入到 **开发者模式**,在 **元素页**搜索其中一个商品id最终发现了存放全部商品id的地方如下:(可以通过 **正则**解析出来)

color&size

既然可以获取全部的商品id,那么通过商品id即可调用评论接口获取对应商品的评论数据了,我们就编码走起!

​

2. 数据采集

数据采集部分,先 **用正则获取全部的商品id**,然后 **通过商品id获取全部商品id对应的评论数据**,那么需要的数据就齐活了。

**获取全部商品id**

import requests
import re
import pandas as pd

headers = {
# "Accept-Encoding": "Gzip", # 使用gzip压缩传输数据让访问更快
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36",
# "Cookie": cookie,
"Referer": "https://item.jd.com/"
}

url= r'https://item.jd.com/100003749316.html'
r = requests.get(url, headers=headers, timeout=6)

text = re.sub(r'\s','',r.text)
colorSize = eval(re.findall(r'colorSize:([.*?])', text)[0])
df = pd.DataFrame(colorSize)


​

**获取商品id对应评论数据**

获取评论信息
def get_comment(productId, proxies=None):
# time.sleep(0.5)
url = 'https://club.jd.com/comment/skuProductPageComments.action?'
params = {
'callback': 'fetchJSON_comment98',
'productId': productId,
'score': 0,
'sortType': 6,
'page': 0,
'pageSize': 10,
'isShadowSku': 0,
'fold': 1,
}
# print(proxies)
r = requests.get(url, headers=headers, params=params,
proxies=proxies,
timeout=6)
comment_data = re.findall(r'fetchJSON_comment98((.*))', r.text)[0]
comment_data = json.loads(comment_data)
comment_summary = comment_data['productCommentSummary']

return sum([comment_summary[f'score{i}Count'] for i in range(1,6)])

df_commentCount = pd.DataFrame(columns=['skuId','commentCount'])
proxies = get_proxies()
for productId in df.skuId[44:]:
df_commentCount = df_commentCount.append({
"skuId": productId,
"commentCount": get_comment(productId, proxies),
},
ignore_index=True
)

df = df.merge(df_commentCount,how='left')


​

3. 统计展示

我们先将尺码中的ABC..罩杯部分单独成列

df['cup'] = df['尺码'].str[-1]


开始我们的简单统计展示吧

先看数据信息概况

df.info()


Int64Index: 64 entries, 0 to 63
Data columns (total 5 columns):
# Column Non-Null Count Dtype

Original: https://www.cnblogs.com/sn5200/p/15817402.html
Author: Python可乐的呀
Title: 利用Python发现60%以上女孩的罩杯是B,但A穿衣却是百搭且很高级

相关阅读3

Title: Python程序语言学习——实验作业04——函数的应用

简要记录下本次实验作业的内容和总结。

实验1. 利用自定义函数求所有水仙花数,并用逗号隔开输出。
所谓水仙花数是一个三位数,其每位上的数字的立方和等于其本身,
如153 = 1^3 + 5^3 + 3^3 故153是水仙花数。

def flowerNumer(n):
    n1 = sum(int(i) ** 3 for i in list(n))
    return n if (int(n) == n1) else 0

if __name__ == '__main__':
    num_list = [str(i) for i in range(100, 1000) if flowerNumer(str(i))]
    print("所有的水仙花数有:" + ','.join(num_list))

实验2. 回文数判断。
设n是一任意自然数,如果n的各位数字反向排列所得自然数与n相等,则n被称为回文数。
从键盘输入一个5位数字,请编写程序判断这个数是不是回文数。
如:123454321和9889就是回文数。

import sys

def palindrome_num(n):
    # reversed()返回的是一个对象,需转换成序列
    n1 = ''.join(reversed(n))
    s = "是回文数" if str(n) == n1 else "不是回文数"
    # n1 = list(reversed(n))
    # s = "是回文数" if list(n) == n1 else "不是回文数"
    # n1 = tuple(reversed(n))
    # s = "是回文数" if tuple(n)==n1 else "不是回文数"
    print(n + s)

def isValid(msg):
    # 若输入的不是整数或者不是5位数  # 输出:"输入不合法!",并不返回任何值
    # 法二:
    # return 1 if msg.isnumeric() and len(msg) == 5 else "输入不合法!"
    if msg.isnumeric() and len(msg) == 5:
        return 1
    else:  # 若输入的不是整数或者不是5位数
        print("输入不合法!")  # 输出:"输入不合法!",并不返回任何值

if __name__ == '__main__':
    while True:
        num = input("请输入一个5位数:")
        if num == '0':
            sys.exit()
        if isValid(num) is None: # 若返回值为None,即输入不合法,重新输入
            continue
        else:  # 否则调用palindrome_num()判断num是否是回文数
            palindrome_num(num)
        #  法二:
        # if isValid(num) == 1:
        #     palindrome_num(num)
        # else:
        #     print(isValid(num))
        #     continue

实验3. 三角形判断。
编写函数判断输入的3个数字是否能构成三角形的3条边。

import sys

def isTriangle(num_t):
    a, b, c = num_t
    if ((a + b) > c) and ((a + c) > b) and ((b + c) > a):
        print("{},{},{} 可以构成一个三角形".format(a, b, c))
    else:
        print("{},{},{} 不可以构成一个三角形".format(a, b, c))

def isValid(n):
    try:
        a, b, c = n.split()
        a = float(a)
        b = float(b)
        c = float(c)
        if a > 0 and b > 0 and c > 0:
            return a, b, c  # 以元组的形式返回三边的值
        else:
            # 若a,b,c任意一个值小于零,不返回任何值
            print("输入不合法!")
    except ValueError:
        # 若a,b,c任意一个值不是整数或小数,不返回任何值
        print("输入不合法!")

if __name__ == '__main__':
    while True:
        num = input("请输入三个数,以空格分隔:")
        if num == '':
            # 当不输入任何字符时,退出程序
            sys.exit('\n退出程序')
        if isValid(num) is None:
            # isValid()无返回值,即输入不合法,继续执行
            continue
        else:
            # 否则 将返回值传入isTriangle()
            isTriangle(isValid(num))

实验4. 七段数码管绘制:通过绘制七段数码管理解使用函数及其封装的价值。

import time
from turtle import *

def drawGap():  # 绘制数码管间隔
    penup()  # 提起笔移动,不绘制图形,用于另起一个地方绘制
    fd(5)  # 向当前画笔方向移动 5 像素长度

def drawLine(draw):  # 绘制单段数码管
    drawGap()  # 调用drawGap() ,绘制间隔
    # turtle.pendown() 移动时绘制图形,缺省时也为绘制
    pendown() if draw else penup() # draw不为0绘制图形,否则另起一个地方
    fd(40)  # 画笔向当前方向绘制40像素长的线条
    drawGap()  # 调用drawGap(),绘制间隔
    right(90)  # 顺时针移动90°

def drawDigit(d):  # 根据数字规制七段数码管
    drawLine(True) if d in [2, 3, 4, 5, 6, 8, 9] else drawLine(False)
    drawLine(True) if d in [0, 1, 3, 4, 5, 6, 7, 8, 9] else drawLine(False)
    drawLine(True) if d in [0, 2, 3, 5, 6, 8, 9] else drawLine(False)
    drawLine(True) if d in [0, 2, 6, 8] else drawLine(False)
    left(90)  # 逆时针移动90°
    drawLine(True) if d in [0, 4, 5, 6, 8, 9] else drawLine(False)
    drawLine(True) if d in [0, 2, 3, 5, 6, 7, 8, 9] else drawLine(False)
    drawLine(True) if d in [0, 1, 2, 3, 4, 7, 8, 9] else drawLine(False)
    left(180)  # 逆时针移动180°
    penup()  # 画笔另起一个新的点
    fd(20)  # 沿当前方向移动20像素

def drawDate(date):
    pencolor('light coral')  # 设置画笔的颜色为淡珊瑚色,默认初始值为黑色
    for i in date:
        if not i.isnumeric():
            sety(-50)
            pencolor('wheat')
            if i == '-':
                write('年', font = ('微软雅黑', 24, 'normal'))
                pencolor('lightblue')  # 设置画笔的颜色为"lightblue"
                fd(45)
            elif i == '=':
                write('月', font = ('微软雅黑', 24, 'normal'))
                pencolor('lightpink')  # 设置画笔的颜色为"lightpink"
            elif i == '+':
                write('日', font = ('微软雅黑', 24, 'normal'))
        else:
            drawDigit(eval(i))
        sety(0)

if __name__ == '__main__':
    # 坐标位置(200,200)处绘制一个大小为 800*350像素的画布
    setup(800, 350, 200, 200)
    screensize(bg = 'lightyellow')
    penup()  # 开始绘制
    hideturtle()  # 绘制完日期,隐藏画笔的turtle形状
    speed('fastest')
    fd(-350)
    pensize(5)  # 定义画笔的大小为 5
    # 使用strftime 方法将 gmtime() 获取的当前的日期以"%Y-%m=%d+"的格式赋值给变量a
    a = time.strftime("%Y-%m=%d+", time.gmtime())
    drawDate(a)  # 调用自定义函数 drawDate()
    done()  # 必须是图形绘制程序的最后一个语句

自定义函数floweNumber(),传入参数为n,用sum()中嵌套元组生成式求各个位数上的数字立方和n1。当满足原数 n == n1时,返回n,否则返回0。

在主函数中,调用自定义函数floweNumber(),传入参数i的范围在[100,1000)内。若返回值不为0,将数字i添加到列表num_list中。最后用','jion(num_list)将所有水仙花数以英文逗号分隔输出。

注意:传入参数i需转换成字符串,以便在floweNumber() 中可以使用sum()中嵌套元组生成式的方式逐个计算每位数的立方和,最后添加到列表时也需要将i转换成字符串,因为join()的参数必须是Iterable的,数字不是Iterable的。

因为需要输入,所以自定义一个对输入值合法的判断的函数 isValid()。根据题目要求,必须是5位数的数字,那么输入值不能是非整数,且长度为5。

定义一个用于判断是否是回文数的函数palindrome_num(),用reversed()反转传入参数n,并赋值给新的变量n1。由于reversed()返回的是一个对象,需转换成序列,我用join()将其转换成字符串。然后比较 str(n) == n1,若相等,字符型 s = "是回文数",否则 s = "不是回文数",最终输出 n+s的结果。即传入值是否是回文数。

在主函数中调用isValid()将输入值num作为参数传入,若满足要求,即是5长度为5的整数,返回1,否则输出"输入不合法!"并且不返回任何值。若判断调用isValid()的值若为None,结束当前循环,重新执行;否则调用自定义函数palindrome_num(),传入num。

变量num获取控制台输入的三个数,以空格间隔。定义一个判断输入值合法的函数isValid(),num作为参数传入,变量a,b,c分别对应输入的三个数,并将三个数转换成float类型,(input()获取的是一个字符串)。判断a,b,c是否都大于0,是则以元组形式返回三个数,否则输出"输入不合法!"并不返回值。在进行前面的操作时,可能会出现因为a,b,c任意一个值不是整数或小数,或者控制台输入的数据不是3个的情况,需要获取try: except获取ValueError异常,输出提示"输入不合法!"并不返回任何值。

在主函数中,首先要对num进行判断是否为空,若为空则退出程序。然后判断调用isValid()函数的返回值是否为None,若是,即输入不合法,终止本次循环,重新执行;否则调用isTriangle() 判断是三个数否能构成三角形。如果输入合法,isValid()返回的是三个数的元组,将返回值传入isTriangle()中,再用变量a,b,c分别获取元组中的三个数,判断是否满足任意两个数之和都大于第三个数,并输出相应的结论。

由于源码是老师提供的,我对源码稍微进行了一点个性化的修改。主要是对其中的一些函数方法进行了学习。接下来,我就在该功能中学习到的新的知识进行一个简单的总结。

属性 描述 turtle.setup(width = 0.5,height = 0.75[,startx = None,starty = None]) width,height为整数时,表示像素;为小数时,表示占据电脑屏幕的比例

(startx,starty)表示矩形窗口左上角顶点的位置,如果为空,则窗口位于屏幕中心。 turtle.penup() 提起笔移动,不绘制图形,用于另起一个地方绘制 turtle.pendown() 移动时绘制图形,缺省时也为绘制 turtle.hideturtle() 隐藏画笔的turtle形状 turtle.forward(distance) 向当前画笔方向移动distance像素长度(或写成fd) turtle.backward(distance) 向当前画笔相反方向移动distance像素长度 turtle.right(degree) 顺时针移动degree° turtle.left(degree) 逆时针移动degree° turtle.sety() 将当前y轴移动到指定位置 turtle.write(s [,font=("font-name",font_size,"font_type")]) 写文本,s为文本内容,font是字体的参数,font为可选项,font参数也是可选项

pencolor() 无参数传入,返回当前画笔颜色,传入参数设置画笔颜色,可以是字符串如"green", "red",也可以是RGB 3元组。 turtle.pensize(size) 设置画笔大小为size个像素 turtle.speed(speed) 设置画笔移动速度,在整数[0,10]内,值越大速度越快 turtle.mainloop() 或

turtle.done() 启动事件循环 -调用Tkinter的mainloop函数。

必须是乌龟图形程序中的最后一个语句。

Original: https://www.cnblogs.com/XSem/p/16154253.html
Author: 阿银呀
Title: Python程序语言学习——实验作业04——函数的应用