[TOC]
函数参数使用注意? 我们分析下,函数的参数需要的是变量,而这里你试图用“元祖”的形式来传递是不可行的。
#author:WeiyiGeek
def MyFun((x, y), (a, b)): #这种方式是Error 的
return x * y - a * b
#而是采用下面这样的方式进行取值
def myFun(x,a)
return x[0] * x[1] - a[0] * b[1]
使用关键字参数,可以有效避免什么问题的出现呢? 关键字参数是指函数在调用的时候,带上参数的名字去指定具体调用的是哪个参数,从而可以不用按照参数的顺序调用函数,可以有效避免因不小心搞乱参数的顺序导致的BUG出现。
请问Python的return语句可以返回多个不同类型的值吗? 可以丫,默认用逗号隔开,是以元祖的形式返回,你当然也可以用列表包含起来返回:
>>> def myFun():
return '操chang', 520, 3.14, True
>>> myFun()
('操chang', 520, 3.14, True)
>>> def myFun2():
return ['甲鱼', 1314, 5.12, False]
>>> myFun2()
['甲鱼', 1314, 5.12, False]
>>>
建议不到万不得已不要使用全局变量,简洁的概括为? a) 代码可读性变差 b) 代码安全性降低
以下关于全局变量的危言耸听是转来的,大家不妨也看下:
在嵌套的函数中,如果希望在内部函数修改外部函数的局部变量,应该使用什么关键字?
#!/usr/bin/python3
def fun1():
x = 5
def fun2():
nonlocal x
x *= 2
return x
return fun2 #注意这里没有括号
demo = fun1()
print(demo()) #值不会被释放,留给下次使用
print(demo())
print(demo())
print(demo())
# 其实大家仔细看看就明白了,当 demo = fun1() 的时候,只要 a 变量没有被重新赋值,fun1() 就没有被释放也就是说局部变量 x 就没有被重新初始化。
# 注意return 函数 带与不带()的区别
#方式1:
def funOut():
def funIn():
print('宾果!你成功访问到我啦!')
return funIn()
#方式2:
def funOut():
def funIn():
print('宾果!你成功访问到我啦!')
return funIn
#在方式1进行调用 funOut()
宾果!你成功访问到我啦!
#在方式2进行调用 funOut()() 采用访问内嵌函数
宾果!你成功访问到我啦!
#或者采用曲线救国 fun = funOut() 就能通过 fun() 访问内嵌函数
省下定义函数过程,使得代码更加精简;不需要考虑命名的问题了;简化代码的可读性
def fun_A(x, y=3):
return x * y
#转换后的lamdba表达式 (注意参数)
lambda x, y=3 : x * y
#利用filter()和lambda表达式快速求出100以内所有3的倍数
list(filter(lambda n : not(n%3), range(1, 100))) #能整除的时候返回1
[3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99]
#列表推导式 ,同样
[ i for i in range(1,100) if not(i % 3)]
那如果拿一个变量当键(Key)可以吗? 肯定不行,因为变量随时都可能改变,不符合可哈希原则!
那有朋友可能会问,元祖总该是不变的吧? 其实不然,因为元祖里边可以存放列表这类可变因素,所以如果实在想拿元祖当字典的键(Key),那必须对元祖做限制:元组中只包括像数字和字符串这样的不可变元素时,才可以作为字典中有效的键(Key)。
注意:Python 的哈希算法对相同的值计算得到的结果是一样的,比 12315 和 12315.0 的值相同,他们被认为是相同的键(Key)。
>>> a = dict(one=1, two=2, three=3)
>>> b = {'one': 1, 'two': 2, 'three': 3}
>>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
>>> d = dict([('two', 2), ('one', 1), ('three', 3)])
>>> e = dict({'three': 3, 'one': 1, 'two': 2})
# 字典可以这样赋值
>>> my = {}
>>> (my['id'],my['name']) = (1024,'Weiyigeek')
>>> (my['id'],my['name']) = "1000,甲鱼".split(',')
# 字典dict1的内容
>>> dict1.fromkeys((1, 3), '数字') #答:执行完成后,字典dict1的内容是:{1: '数字', 3: '数字'}
Windows在路径名中既可以接受斜线(/)也可以接受反斜线(\),不过如果使用反斜线作为路径名的分隔符的话,要注意使用双反斜线(\)
f = open('E:/test.txt', 'w') # A
f = open('E:\\test.txt', 'w') # C
f = open('E:\\Test.bin', 'xb')
#注意的是'x'和'w'均是以“可写入”的模式打开文件,但以'x'模式打开的时候,如果路径下已经存在相同的文件名,会抛出异常,而'w'模式的话会直接覆盖同名文件(比较危险)。
open()函数默认的打开模式是’rt’(即可读、文本的模式打开)
Python可能会缓存你写入的数据,如果这中间断电了神马的,那些缓存的数据根本就不会写入到文件中,所以建议是哟个 f.close() 将缓存数据写入并关闭文件
将一个文件对象(f)中的数据存放进列表 , 直接list(f)。
在进行截取和偏移的时候,需要注意打开文件的编码格式,如以GBK编码则(一个汉字需要占用两个字节),所以需要*2进行截取。
常见异常情况?
>>> my_list = [1, 2, 3, 4,,] #SyntaxError: invalid syntax
>>> my_list = [1, 2, 3, 4, 5]
>>> print(my_list[len(my_list)]) #试图访问 my_list(5) 会引发 IndexError: list index out of range 异常。
>>> my_list.sorted() #AttributeError: 'list' object has no attribute 'sorted'
>>> my_dict = {'host': 'http://bbs.fishc.com', 'port': '80'}
>>> print(my_dict['server']) #不存在的“键”引发 KeyError: 'server' 异常
f = open('C:\\test.txt', wb) #注意 open() 第二个参数是字符串 否则引发 NameError 异常
f.write('I love FishC.com!\n')
f.close()
except 后边如果不带任何异常类,Python 会捕获所有(try 语句块内)的异常并统一处理,但却不建议这么做,你知道为什么吗? 答:因为它会隐藏所有程序员未想到并且未做好准备处理的错误,例如:用户输入ctrl+c试图终止程序会被解释为KeyboardInterrupt异常。 使用 with 语句相当方便,with 语句会自动处理文件的打开和关闭(with open(‘data.txt’, ‘w’) as f),如果中途出现异常会执行清理代码,然后确保文件自动关闭。
min() 这个BIF的实现过程还原? sum()BIF有个缺陷,就是如果参数里有字符串类型的话就会报错,写出一个新的实现过程自动“无视”参数里的字符串并返回正确的计算结果?
#!/usr/bin/python3
# min 内置函数的实现 与 sum bug 解决
#author:WeiyiGeek
def min(x):
initvalue = x[0]
for each in x:
if each < initvalue: #实际采用的ASCII进行比对的
initvalue = each
else:
print("计算成功")
return initvalue
def sum(x):
result = 0
for each in x:
if isinstance(each,int) or isinstance(each,float):
result += each
return result;
print("min",min('178546810'))
print("sum",sum([1,3,6.6,'y',"abcd"]))
##### 计算成功结果 ######
# min = 0
# sum = 10.6
编写一个函数 findstr(),该函数统计一个长度为 2 的子字符串在另一个字符串中出现的次数。例如:假定输入的字符串为“You cannot improve your past, but you can improve your future. Once time is wasted, life is wasted.”,子字符串为“im”,函数执行后打印“子字母串在目标字符串中共出现 3 次”。
#author:WeiyiGeek
#方法1:count()方法
def findstr1():
string = "You cannot improve your past, but you can improve your future. Once time is wasted, life is wasted."
temp = input("请输入字符串:")
if temp.isspace() or len(temp) <= 2:
temp = string
temp1 = input("输入查找的字符串(两个以上):")
while len(temp1) < 2:
temp1 = input("查找字符长度有误,请重新输入:")
print(temp.count(temp1))
findstr1()
#方法2:
def findStr(desStr, subStr):
count = 0
length = len(desStr)
if subStr not in desStr:
print('在目标字符串中未找到字符串!')
else:
for each1 in range(length-1):
if desStr[each1] == subStr[0]: #主要代码在这里判断连续的两个字符是不相等
if desStr[each1+1] == subStr[1]:
count += 1
print('子字符串在目标字符串中共出现 %d 次' % count)
desStr = input('请输入目标字符串:')
subStr = input('请输入子字符串(两个字符):')
findStr(desStr, subStr)
########## 输出结果 ###############
# 请输入字符串:tesadasdsadasdasdasdasdasd
# 输入查找的字符串(两个以上):as
# 6
编写一个函数,判断传入的字符串参数是否为“回文联”(回文联即用回文形式写成的对联,既可顺读,也可倒读。例如:上海自来水来自海上)
def palindrome(string):
length = len(string)
last = length-1
length //= 2
flag = 1
for each in range(length):
if string[each] != string[last]:
flag = 0
last -= 1
if flag == 1:
return 1
else:
return 0
string = input('请输入一句话:')
if palindrome(string) == 1:
print('是回文联!')
else:
print('不是回文联!')
#方法2:
def palindrome(string):
list1 = list(string)
list2 = reversed(list1)
if list1 == list(list2):
return '是回文联!'
else:
return '不是回文联!'
print(palindrome('上海自来水来自海上'))
#方法3:递归方式
def is_palindrome(n, start, end):
if start > end:
return 1
else:
return is_palindrome(n, start+1, end-1) if n[start] == n[end] else 0
string = input('请输入一串字符串:')
length = len(string)-1
if is_palindrome(string, 0, length):
print('"%s"是回文字符串!' % string)
else:
print('"%s"不是回文字符串!' % string)
#请输入一段话:上海自来水来自海上
#回文数
编写一个函数,分别统计出传入字符串参数(可能不只一个参数)的英文字母、空格、数字和其它字符的个数。
#!/usr/bin/python
#author:WeiyiGeek
def count(*param):
length = len(param)
for i in range(length):
letters = 0
space = 0
digit = 0
others = 0
for each in param[i]: #区别是第几个字符串
if each.isalpha(): #用得很好
letters += 1
elif each.isdigit():
digit += 1
elif each == ' ':
space += 1
else:
others += 1
print('第 %d 个字符串共有:英文字母 %d 个,数字 %d 个,空格 %d 个,其他字符 %d 个。' % (i+1, letters, digit, space, others))
count('I love weiyigeek.github.io.', 'I love you, you love me.')
####################### 输出结果 ################################
# 第 1 个字符串共有:英文字母 18 个,数字 0 个,空格 2 个,其他字符 2 个。
# 第 2 个字符串共有:英文字母 17 个,数字 0 个,空格 5 个,其他字符 2 个。
# 请按任意键继续. . .
游戏中的角色移动:闭包(closure)在实际开发中的作用? 在某种情况下,我们并不方便使用全局变量,所以灵活的使用闭包可以实现替代全局变量。 在游戏开发中,我们需要将游戏中角色的移动位置保护起来,不希望被其他函数轻易可以修改到,所以我们选择使用闭包操作,参考代码及注释如下:
# -*- coding: utf8 -*-
origin = (0,0)
legalx = [-100,100]
legaly = [-100,100]
def create(posx=0,posy=0):
def moving(direction,step):
# direction参数设置方向,1为向右(向上),-1为向左(向下),0为不移动
# step参数设置移动的距离
nonlocal posx,posy
newx = posx + direction[0] * step
newy = posy + direction[1] * step
# 检查移动后是否能够超出X轴边界
if newx<legalx[0]:
posx = legalx - (newx - legalx) # -100 - (-101 + 100) => -100 + 1 ==> -99
elif newx > legalx[1]:
posx = legalx[1] - (newx - legalx[1]) # 100 - (101 - 100) => 99
else:
posx = newx
#注意这里,会返回到下一次的调用之中
# 检查移动后是否超出y轴边界
if newy < legaly[0]:
posy = legaly - (newy - legaly)
elif newy > legaly[1]:
posy = legaly[1] - (newy - legaly[1])
else:
posy = newy
return posx,posy
return moving
move = create()
print('向右移动10步后,位置是:', move([1, 0], 10))
print('向上移动130步后,位置是:', move([0, 1], 130))
print('向左移动10步后,位置是:', move([-1, 0], 10))
注意:的一点是:move = create(),如果当 move 变量重新被赋值的话,相应的 pos_x 和 pos_y 也都会被初始化为 0。
请用已学过的知识编写程序,统计下边这个长字符串中各个字符出现的次数.
str1 = '''拷贝过来的字符串'''
list1 = []
for each in str1:
if each not in list1: #如果不在 list1 中,执行统计
if each == '\n':
print('\\n', str1.count(each))
else:
print(each, str1.count(each)) #使用比较精辟
list1.append(each)
使用递归算法求解下面二的问题 Q:有5个人坐在一起,问第五个人多少岁?他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。问第三个人,又说比第2人大两岁。问第2个人,说比第一个人大两岁。最后问第一个人,他说是10岁。请问第五个人多大? 解题思路:利用递归的方法,递归分为回推和递推两个阶段。要想知道第五个人岁数,需知道第四人的岁数,依次类推,推到第一人(10岁),再往回推。
#!/usr/bin/python
def age(n):
if n == 1:
return 10
else:
return age(n-1)+2
print('哈哈,我知道了,第五个人的年龄是 %d 岁,啵啵脆!' % age(5))
采用字典写出通讯录
print('|--- 欢迎进入通讯录程序 ---|')
print('|--- 1:查询联系人资料 ---|')
print('|--- 2:插入新的联系人 ---|')
print('|--- 3:删除已有联系人 ---|')
print('|--- 4:退出通讯录程序 ---|')
contacts = dict()
while 1:
instr = int(input('\n请输入相关的指令代码:'))
if instr == 1:
name = input('请输入联系人姓名:')
if name in contacts:
print(name + ' : ' + contacts[name])
else:
print('您输入的姓名不再通讯录中!')
if instr == 2:
name = input('请输入联系人姓名:')
if name in contacts:
print('您输入的姓名在通讯录中已存在 -->> ', end='')
print(name + ' : ' + contacts[name])
if input('是否修改用户资料(YES/NO):') == 'YES':
contacts[name] = input('请输入用户联系电话:')
else:
contacts[name] = input('请输入用户联系电话:')
if instr == 3:
name = input('请输入联系人姓名:')
if name in contacts:
del(contacts[name]) # 也可以使用dict.pop()
else:
print('您输入的联系人不存在。')
if instr == 4:
break
print('|--- 感谢使用通讯录程序 ---|')
用函数模块的形式进行封装用户登陆注册模块
#!/usr/bin/python3
# 功能:登陆login/register
user_data = {}
'提示'
def tip():
print("###### 新建用户:N/n ######")
print("###### 登陆用户:E/e ######")
print("###### 登陆用户:Q/q ######")
'注册模块'
def reg():
name = input("请输入注册名用户名")
while True:
if name in user_data:
name = input("用户名已被占用,请重新输入:")
else:
break
password = input("请输入密码:")
user_data.setdefault(name, password)
print("Ok.注册成功")
'登陆模块'
def login():
name = input("请输入登陆的账户:")
while True:
if name not in user_data:
name = input("输入的用户名不存在,请重新输入用户名:")
else:
break
password = input("请输入密码:")
if user_data[name] == password:
print("Ok.登陆成功")
else:
print("Error.密码错误")
'主模块'
def user():
tip()
while 1:
temp = input("|---请输入指令代码:")
if temp.lower() == 'n':
reg()
if temp.lower() == 'e':
login()
if temp.lower() == 'q':
break
print("退出成功,欢迎下次使用!")
user() #调用主模块
################# 结果输出 ###############
###### 新建用户:N/n ######
###### 登陆用户:E/e ######
###### 登陆用户:Q/q ######
# |---请输入指令代码:N
# 请输入注册名用户名weiyigeek
# 请输入密码:5
# Ok.注册成功
# |---请输入指令代码:e
# 请输入登陆的账户:weiyigeek
# 请输入密码:5
# Ok.登陆成功
# |---请输入指令代码:q
# 退出成功,欢迎下次使用!
文件操作案例(1),指定字符输入完毕后写入文件中
#!/usr/bin/python3
#文件操作
#方式1
filename = input("请输入一个文件名:")
f = open(filename,'x',encoding='utf-8')
list1 = []
print(r'"请输入内容,单独输入\':w\'保存:"')
while True:
value = input()
if value != ":w":
list1.append(value+'\n')
else:
f.writelines(list1) #注意这里是直接使用 writelines 将列表值暂时写入到文件中
break
f.close() #关闭文件
#方法2:
while True:
write_some = input()
if write_some != ':w':
f.write('%s\n' % write_some) # write 不能直接将列表值写入到文件中 需要进行循环写入
else:
break
################# 结果输出 ###############
# 请输入一个文件名:test.txx
# "请输入内容,单独输入\':w\'保存:"
# test
# Pyton
# asdsa
# 123546678
# :w
用户可以随意输入需要显示的行数。(如输入13:21打印第13行到第21行,输入:21打印前21行,输入21:则打印从第21行开始到文件结尾所有内容)
def file_view(file_name, line_num):
if line_num.strip() == ':':
begin = '1'
end = '-1'
(begin, end) = line_num.split(':')
if begin == '':
begin = '1'
if end == '':
end = '-1'
if begin == '1' and end == '-1':
prompt = '的全文'
elif begin == '1':
prompt = '从开始到%s' % end
elif end == '-1':
prompt = '从%s到结束' % begin
else:
prompt = '从第%s行到第%s行' % (begin, end)
print('\n文件%s%s的内容如下:\n' % (file_name, prompt))
begin = int(begin) - 1
end = int(end)
lines = end - begin
f = open(file_name)
for i in range(begin): # 用于消耗掉begin之前的内容
f.readline()
if lines < 0:
print(f.read())
else:
for j in range(lines):
print(f.readline(), end='')
f.close()
file_name = input(r'请输入要打开的文件(C:\\test.txt):')
line_num = input('请输入需要显示的行数【格式如 13:21 或 :21 或 21: 或 : 】:')
file_view(file_name, line_num)
打开文件操作使用案例
os模块使用案例文件统计搜寻及文件扩展名
#!/usr/bin/python3
#OS模块的使用
import os
all_files = os.listdir(os.curdir) # 使用os.curdir表示当前目录更标准 | 显示当前目录与文件
type_dict = dict() #类型
file_dict = dict() #文件及大小
for each_file in all_files:
if os.path.isdir(each_file):
type_dict.setdefault('文件夹', 0)
type_dict['文件夹'] += 1
else:
#扩展名文件统计
ext = os.path.splitext(each_file)[1]
type_dict.setdefault(ext, 0) #注意 当字典里面不存在的时候才会建立赋值为0 , 否则不对字典里面key/VALUE值进行操作
type_dict[ext] += 1 #直接进行字典value运算
#文件大小统计
file_dict.setdefault(each_file,os.path.getsize(each_file))
#统计文件类型格式
for each_type in type_dict.keys():
print('该文件夹下共有类型为【%s】的文件 %d 个' % (each_type, type_dict[each_type]))
#显示文件及其大小
for each_size in file_dict.items():
print("fileName:%s , Size: %dBytes" %(each_size[0],each_size[1]))
vedio_list = []
#用户输入文件名以及开始搜索的路径
def search_file(start_dir, target) :
os.chdir(start_dir) #进入目录
for each_file in os.listdir(os.curdir) :
if each_file == target :
print(os.getcwd() + os.sep + each_file) # 使用os.sep是程序更标准
break
if os.path.isdir(each_file) :
search_file(each_file, target) # 递归调用
os.chdir(os.pardir) # 递归调用后切记返回上一层目录
print("搜寻到文件:")
search_file(os.curdir,'homework1.py')
#按照扩展名进行搜寻
# targetext = ['avi','txt','py']
# if ext in targetext :
# vedio_list.append(os.getcwd() + os.sep + each_file + os.linesep) # 使用os.sep是程序更标准
################ 执行案例 ###################
# 该文件夹下共有类型为【文件夹】的文件 3 个
# 该文件夹下共有类型为【.py】的文件 5 个
# fileName:demo3.0.py , Size: 1528Bytes
# fileName:demo3.1.py , Size: 1062Bytes
# fileName:demo3.2.py , Size: 1319Bytes
# fileName:demo3.3.py , Size: 1850Bytes
# fileName:homework1.py , Size: 1677Bytes
# 搜寻到文件:
# C:\Users\Administrator\Desktop\Python\1\homework1.py
# C:\Users\Administrator\Desktop\Python\2\homework1.py
# C:\Users\Administrator\Desktop\Python\homework1.py
用户输入关键字,查找当前文件夹内(如果当前文件夹内包含文件夹,则进入文件夹继续搜索)所有含有该关键字的文本文件(.txt后缀),要求显示该文件所在的位置以及关键字在文件中的具体位置(第几行第几个字符)
import os
def print_pos(key_dict):
keys = key_dict.keys()
keys = sorted(keys) # 由于字典是无序的,我们这里对行数进行排序
for each_key in keys:
print('关键字出现在第 %s 行,第 %s 个位置。' % (each_key, str(key_dict[each_key])))
def pos_in_line(line, key):
pos = []
begin = line.find(key)
while begin != -1:
pos.append(begin + 1) # 用户的角度是从1开始数
begin = line.find(key, begin+1) # 从下一个位置继续查找
return pos
def search_in_file(file_name, key):
f = open(file_name)
count = 0 # 记录行数
key_dict = dict() # 字典,用户存放key所在具体行数对应具体位置
for each_line in f:
count += 1
if key in each_line:
pos = pos_in_line(each_line, key) # key在每行对应的位置
key_dict[count] = pos
f.close()
return key_dict
def search_files(key, detail):
all_files = os.walk(os.getcwd())
txt_files = []
for i in all_files:
for each_file in i[2]:
if os.path.splitext(each_file)[1] == '.txt': # 根据后缀判断是否文本文件
each_file = os.path.join(i[0], each_file)
txt_files.append(each_file)
for each_txt_file in txt_files:
key_dict = search_in_file(each_txt_file, key)
if key_dict:
print('================================================================')
print('在文件【%s】中找到关键字【%s】' % (each_txt_file, key))
if detail in ['YES', 'Yes', 'yes']:
print_pos(key_dict)
key = input('请将该脚本放于待查找的文件夹内,请输入关键字:')
detail = input('请问是否需要打印关键字【%s】在文件中的具体位置(YES/NO):' % key)
search_files(key, detail)
Weiyigeek.os.path使用
try except 文件打开异常案例
#!/usr/bin/python3
#功能:课后作业
try:
f = open('My_File.txt') # 当前文件夹中并不存在"My_File.txt"这个文件T_T (而且是一个局部变量)
print(f.read())
except OSError as reason:
print('出错啦:' + str(reason))
finally:
if 'f' in locals(): # 如果文件对象变量存在当前局部变量符号表的话,说明打开成功
f.close()
##################### 结果 ################################
#出错啦:[Errno 2] No such file or directory: 'My_File.txt'
#请按任意键继续. . .
目录中所有文件的行数统计?
#!/usr/bin/python3
#功能:代码行数统计
import os
count = 0 # 代码行数
def filecount(dirpath):
global count
os.chdir(dirpath)
for each_file in os.listdir(os.curdir):
if os.path.isfile(each_file):
with open(each_file,'r',encoding='utf8') as f:
for index,value in enumerate(f):
count += 1
elif os.path.isdir(each_file):
filecount(each_file)
os.chdir(os.pardir)
filecount('C:\\Users\\Administrator\\Desktop\\JAVA-Study')
print("当前目录中一共写了%d 行代码" %count)
#################执行结果########################
#C:\Users\Administrator\Desktop\Python>python codecount.py
#当前目录中一共写了112 行代码