函数def
定义函数
1,我们可以把程序中相对独立的功能模块抽取出来
这样做的好处:一是减少重复代码的编写,二是将来可以重复的使用这些功能模块
2,Python中的函数就是代表了这样的功能模块
y = f(x): f是函数名,x是自变量,y是因变量
定义一个函数时括号内的自变量可以是0个也可以是多个
Python中定义函数官方建议开头和结尾空出两行
注意:如果要重命名函数,选中函数名右键重构重命名,不要手动一个一个去改名,这样既浪费时间又有可能漏改!!!
在使用模块时容易出现命名冲突如果从不同模块导入了两个重名的函数,系统会自动屏蔽掉一个;其中后定义的那一个生效,
它会自动覆盖掉它之前的那一个函数;也可以通过使用一个函数后再次导入另一个函数。
我们也可以给自己定义的函数用别名取代imort ... as ...
在导入一个模块时如果名字太长想改短,也可以用别名import ... as ...
在导入一个函数时Ctrl + 左键可以看到该函数的定义
- 定义一个求阶乘的函数 - 将求阶乘的功能抽取出来放到函数中
def f(x):
# 文档注释:三引号开头,三引号结尾,在使用时对函数按快捷键Ctrl + q可以看到这个注释
'''
计算阶乘
:param x:一个非负整数
:return: 阶乘
'''
y = 1
for num in range(1, x + 1):
y *= x
return y
m = int(input('m = '))
n = int(input('n = '))
# 当需要计算阶乘的时候不用再写循环,而是直接调用已经定义好的函数
print(f(m - n))
print(f(m) // f(n) // f(m - n))
- 定义摇两颗色子的函数,它会返回摇出的点数
def roll_two_dice():
face1 = randint(1, 6)
face2 = randint(1, 6)
return face1 + face2
# 定义变量中的n = 2表示没有给变量的时候默认值为2,当代码中用户输入变量的时候函数的变量就是用户输入的值。
# 定义变量默认值的时候等号两边不建议加空格,在使用这个函数时变量等号两边也不加空格
def roll_dice(n=2):
total = 0
for _ in range(n):
total += randint(1,6)
return total
- 调用某个文件中定义的一个函数
import is_prime().xxx
from xxx import is_prime()
# 这种后面加*的表示导入xxx中所有的函数
from xxx import *
# 计算最大公约数的函数
def gcd(x, y):
# Python中的三元条件运算,if条件成立取前面的值,否则取后面的值
(x, y) = (y, x) if x > y else (x , y)
# 在range循环中如果要让循环倒着跑,可以把步长设置成 - 1
for factor in range(x, 0 ,-1):
if x % factor == 0 and y % factor == 0:
return factor
# 计算最小公倍数的函数
def lcm(x, y):
return x * y // gcd(x, y)
# 通过下面的if条件可以在导入模块时不去执行原模文件下除函数外的代码
# __name__是Python中一个隐含的变量它代表了模块的名字
# 只有被Python解释器直接执行的模块的名字才是__main__
if __name__ == '__main__':
number = int(input('number = '))
print(is_prime(number))
- 可变参数 - 在不确定要输入的参数个数时,定义 *args,参数可以有0或任意多个
def add(*args):
total = 0
for value in args:
total += value
return total
print(add(5,6,7))
- 判断一个数是不是回文数
def is_palindrome(num):
'''
判断一个数是不是回文数
:param num: 一个非负整数
:return: 是回文数返回True否则返回False
'''
temp = num
total = 0
while temp > 0:
total = total * 10 + temp % 10
temp //= 10
return total == num
number = int(input('请输入一个非负整数:'))
# and和pr运算符都是带短路功能的运算符
# 如果and左边的表达式是False那么右边的表达式被短路(不执行)
# 如果or左边的表达式是True那么右边的表达式被短路
# 所以左右两边的表达式放置的顺序可能会对程序的执行效率产生明显的影响。通常把运算量小的放左边!
if is_palindrome(number) and is_prime(number):
print('%d是回文素数' % number)
else:
print('%d不是回文素数' % number)
作用域
Python中搜索一个变量的方式是从局部作用域到嵌套作用域再到全局作用域再到内置作用域
Local - Enclosed - Global - 内置作用域 (L - E - G - B)
如果想改变搜索范围,可以使用gloabl和nonlocal关键字
实际开发时一定要尽可能减少全局变量的使用!遵循迪米特法则:尽量不要让模块之间产生关联
a = 100
b = 'good'
# gloable variable在函数外面定义的a是一个全局变量
def foo():
# local variable函数内的局部变量,离开foo函数变量a是无法访问的
# 如果函数内想要调用全局变量,就在变量前加上global
# 这里调用全局变量,会影响到后面全局变量的值
global a
a = 200
b = 'hello'
def bar():
# 这里如果想要搜索外部的b,用嵌套作用域nonlocal
# nonlocal b
b = hello
print(a)
print(b)
bar(b)
a = 200
print(a)
- 定义一个函数求阶乘
# 这里可以使用递归算法
# 使用递归的条件1:收敛条件 - 让递归在有限的次数内完成或者进行回溯
# 如果递归无法在有限次数内收敛就有可能导致RecursionError
# 2:递归公式
# 函数可以自己调用自己,但是不能无休止的调用
def f(n):
if n == 0 or n == 1:
return 1
return n * f(n - 1)
if __name__ == '__main__':
# 在进入函数调用之前要保存当前的执行现场
# 函数的执行现场是保存在一种称为栈(stack)的内存空间上
# 栈是一种先进后出(FILO)的存储结构
print(f(65))
- 小女孩走10级台阶,可以一次走一阶/两阶/三阶,有多少种走法
def walk(n):
if n < 0:
return 0
elif n == 0:
return 1
return walk(n - 1) + walk(n - 2) + walk(n - 3)
if __name__ == '__mian__':
mian()
字符串str
def main():
# 查help也可以这样用
print(help(''.capitalize))
# 不变字符串
str1 = 'hello, world!'
print(len(str1))
print(str1.capitalize())
print(str1.upper())
print(str1)
print(str1.find('or'))
print(str1.find('shit'))
print(str1.index('or'))
# 用index如果查找没有结果的话会报错停止程序运行
print(str1.startswith('He'))
print(str1.startswith('hel'))
print(str1.endswith('!'))
print(str1.center(50, '*'))
print(str1.rjust(50, ' '))
str2 = 'abc123456'
# 字符串切片操作
print(str2[2])
print(str2[2:5])
print(str2[2::2])
print(str2[:])
print(str2[::2])
print(str2[::-1])
print(str2[-3:-1])
print(str2[-1:-3:-1])
# 检查字符串是否由数字构成
print(str2.isdigit())
# 检查字符串是否以字母构成
print(str2.isalpha())
# 检查字符串是否以数字和字母构成
print(str2.isalnum())
str3 = ' dsagoihsdlkj '
print(str3)
# 获得字符串修剪左右两侧空格的拷贝
print(str3.strip())
if __name__ == '__main__':
main()
- 设计一个函数,给一个文件名,把后缀名提取出来
# abc. .abc
def get_suffix(filename,has_dot=False):
'''
获取文件名的后缀名
:param filename: 文件名
:param has_dot: 后缀名是否带.
:return: 文件名的后缀
'''
pos = filename.rfind('.')
if 0 < pos < len(filename) - 1:
index = pos if has_dot else pos + 1
return filename[index:]
else:
return ''
if __name__ == '__main__':
print(get_suffix('awdsd.exe'))
列表list
有了列表(容器)我们可以使用1个变量来保存多个数据,更为重要的是我们可以使用循环对列表中保存的数据进行操作。
列表生成表达式语法创建列表容器,用这种语法创建列表之后元素已经准备就绪,所以需要消耗较多的内存空间。
列表生成器得到的不是一个列表,而是一个生成器对象,通过生成器可以获取到数据,它不占用额外的空间存储数据,每次需要数据的时候就通过内部的运算得到数据,但这需要花费时间。
def main():
list1 = [1, 2, 3, 4, 5]
print(list1)
list2 = ['hello','world','Python']
print(list2)
print(len(list1))
# 下标运算
print(list1[0])
print(list1[4])
print(list1[-1])
print(list1[-3])
list1[2] = 300
print(list1)
# 添加元素
list1.append(200)
list1.insert(1, 400)
list1 += [1000, 2000]
print(list1)
print(len(list1))
# 删除元素
list1.remove(3)
if 1234 in list1:
list1.remove(1234)
del list1[0]
print(list1)
# 清空列表元素
list1.clear()
print(list1)
list3= ['sfjoiej', 'askg', 'beoihg', 'wjwoieg']
list3 += ['jasdkn', 'pass', 'ewvgh']
# 循环遍历列表元素
for list in list3:
print(list.title(), end=' ')
print()
# 列表切片
list4 = list3[1:4]
print(list4)
list5 = list3[:]
print(list5)
list6 = list3[-3:-1]
print(list6)
# 可以通过反向切片操作来获得倒转后的列表的拷贝
list7 = list3[::-1]
print(list7)
# 列表排序
f = ['blue', 'red', 'orange','icecream', 'pepsi']
# Python内置的排序方法默认都是排升序(从小到大)
# 如果希望排列成降序,可以通过reverse参数来指定
# Python中的函数几乎都是没有副作用的函数
# 调用函数之后不会影响传入的参数
f2 = sorted(f, reverse = True)
print(f)
print(f2)
f.sort(reverse=True)
print(f)
f.reverse()
# f3是直接在f上进行反转,如果不加f3 = ,返回的是把f里元素反转后f的结果
f3 = reversed(f)
print(f3)
# 通过输入关键字类型来进行排序
f4 = sorted(f, key=str_len, reverse=True)
print(f4)
if __name__ == '__main__':
main()
import sys
def main():
f = (x ** 2 for x in range(1, 100))
print(sys.getsizeof(f))
for val in f:
print(val,end = '\t')
if __name__ == '__main__':
main()
def f(*args):
total = 0
for val in args:
total += val
return total
# 把一个列表当成可变参数传入函数,不能直接print(f(my_list))需要用 *args 把列表拆散传入函数
my_list = [1,2,3,4,5]
print(f(*my_list))
# 枚举enumerate,也是一种数据类型,这种数据类型只包含自定义的特定数据,它是一组有共同特性的数据的集合
def main():
f = [100, 200, 300]
for index, val in enumerate(f):
print(index, ':', val)
# CRUD操作 Create Read Update Delate
f.append(123)
f.insert(1,300)
print(f)
if 300 in f:
f.remove(300)
# f.clear()
del f[3]
print(f)
# print(f.index(100, 3, 5))
# pop:移除列表中的一个元素(默认最后一个元素),并且返回该元素的值
print(f.pop(1))
print(f)
if __name__ == '__main__':
main()
- 生成一个斐波拉切数列 fn = f(n-1)+ f(n-2)
def main(n=2):
f = [1, 1]
print(f)
for index in range(2, n):
val = f[index - 1] + f[index - 2]
f.append(val)
print(f)
if __name__ == '__main__':
main()
- 设计一个函数,从传入的列表中找出第二大的元素(要求只能使用一次循环)
def second_max(x):
# 元组
# 元组是只读的,不能写
(m1,m2) = (x[0], x[1]) if x[0] > x[1] else (x[1], x[0])
for index in range(2, len(x)):
if x[index] > m1:
m2 = m1
m1 = x[index]
elif x[index] > m2:
m2 = x[index]
return m2
def main():
my_list = [23,554,43,56,87,355,76]
print(second_max(my_list))
if __name__ == '__main__':
main()
- 有30个人坐船出海,途中船坏了只能承载15人,于是这30人围城一圈,从第一个人开始报数,报到9的人就丢进海里,下一个人重新开始报数,以此类推,结果 最后船上剩余的人全是基督徒,问之前这些人站的位置?
# 这里可以用约瑟夫环来解决这个问题
def main():
persons = [True] * 30
counter = 0
index = 0
number = 0
while counter < 15:
if persons[index]:
number += 1
if number == 9:
persons[index] = False
counter += 1
number = 0
index += 1
# if index == 30:
# index = 0
index = index % 30
for person in persons:
print('基' if person else '非',end='')
if __name__ == '__main__':
main()
元组tuple
元组与列表类似,不同的在于元组中的元素不可修改,也就是说元组是只读的
集合
列表是有顺序的,能用小标来取元素
集合是离散存储数据,没有顺序,无法用下标来取元素,可以用遍历pop,但是取出来的元素不确定
def main():
set1 = {1,1,2,2,3,3}
set1.add(4)
set1.add(5)
# 集合中输入重复的元素输出时只有一个,因为集合中不允许出现重复的元素
print(set1) # {1,2,3,4,5}
set2 = {1,2,3,4,5,7,9}
print(set2)
set3 = set1.intersection(set2)
print(set3)
set4 = set1.union(set2)
print(set4)
set5 = set1 & set2
print(set5)
set6 = set1 | set2
print(set6)
set7 = set2 - set1
print(set7)
print(set1 <= set2)
set2 = {'hello','good','banana','zoo','puthon','apple'}
print(len(set12))
x = sorted(set2)
print(type(x))
list1 = list(set2)
print(list1)
list2 = [1,2,3,1,2,4]
set2 = set(list2)
print(set2)
tuple = (1,1,2,3,4,4)
list3 = list(tuple)
print(list3)
set3 = set(tuple)
if __name__ == '__main__':
main()
- 定义一个函数,生成一个成绩列表
def main():
names = ['关羽','张飞','赵云','马超','貂蝉']
subjects = ['语文','数学','python']
# table = [[0] * len(subjects) * len(names)]这个方式复制的是5个列表的元素地址,输出结果5个列表会完全一样
# 下面的复制列表就不会出现这样的问题
table = [[0] * len(subjects) for _ in range(len(names))]
for x,name in enumerate(names):
print('请输入%s的成绩:' % name)
for y,subject in enumerate(subjects):
score = int(input('%s:' % subject))
table[x][y] = score
print(table)
if __name__ == '__main__':
main()
字典dict
字典可以存储任意类型对象,字典的每个元素都是由一个键和一个值组成的“键值对”,键和值通过冒号分开。
def main():
dict1 = {'name':'赵信','age':25,'gender':True}
print(dict1['name'])
print(dict1['age'])
print(dict1['gender'])
dict1['name'] = '一叶知秋'
print(dict1)
# dict1 += {'tel':'123445678'}
dict1.update(height=178, fav=['吃,玩'])
print(dict1)
print(dict1.pop('age'))
print(dict1.popitem())
dict1['name'] = None
for x in dict1:
print(x,'--->',dict1[x])
if __name__ == '__main__':
main()
面向对象
对象特征:1,一切都是对象
2,对象都有属性(静态特征)和行为(动态特征)
3,每个对象都是独一无二的
4,对象一定会归属到某个类(类型/类别),类是对象的蓝图和模板
类是抽象的,对象是具体的
step 1,定义类
类是对象的蓝图和模板,有了类就可以创建对象
定义类需要做两件事:数据抽象和行为抽象
数据抽象 - 抽取对象共同的静态特征(找名词) - 属性
行为对象 - 抽取对象共同的动态特征(找动词) - 方法
定义类的关键字 - class - 类名(每个单词首字母大写)
step 2,调用构造方法创建对象
step 3,给对象发消息
注意 自己定义的类每个单词首字母都要大写
写在类里面的def叫方法,方法与方法之间至少要留一个空行
我们定义一个类实际上是把数据和操作数据的函数绑定到一起,形成一个逻辑上的整体,这个整体就叫对象,
而且将来任何时候想使用这种对象时直接复用这个类就可以了
# object是Python内置的一个类
class Student(object):
# init初始化/设定默认值
# __init__构造方法(构造器/构造子 - constructor)
# 调用改方法的时候不是直接使用方法的名字,而是使用类的名字
def __init__(self,name,age):
# 给对象绑定属性
self.name = name
self.age = age
# 我们定义一个方法就代表对象可以接收这个消息
# 对象的方法的第一个参数都是统一写成self
# 它代表了接收消息的对象 - 对象.消息(参数)
def study(self,course):
# self.表示接收消息的对象
print('%s正在学习%s' % (self.name, course))
def watch_av(self):
if self.age >= 18:
print('%s正在观看岛国爱情动作片' % self.name)
else:
print('%s,我们推荐你观看《天线宝宝》' % self.name)
def main():
# 调用构造方法创建学生对象
# 实际上调用的是Student
stu1 = Student('李牧',40)
# 给对象发消息
# 通过给对象发消息,让对象完成某些工作,就可实现程序的功能
# 解决任何问题都是通过让对象去做事情来解决的
stu1.study('Python程序设计')
stu2 = Student('钟岳',17)
stu2.study('HTML网页设计')
stu2.watch_av()
if __name__ == '__main__':
main()
- 写一个类,显示数字时钟
class Clock(object):
'''时钟'''
def __init__(self, hour = 0, minute = 0, second = 0):
# 构造器...
self._hour = hour
self._minute = minute
self._second = second
def run(self):
''' 走字'''
self._second += 1
if self._second == 60:
self._second = 0
self._minute += 1
if self._minute == 60:
self._minute = 0
self._hour += 1
if self._hour == 24:
self._hour = 0
# 这是一个特殊方法
# 下面的方法可以获得对象的字符创表示形式
# 当我们用print打印对象时会自动调用该方法
# def __str__(self):
def show(self):
'''
显示时间
:return:时间
'''
return '%02d:%02d:%02d' % (self._hour, self._minute,self._second)
from time import sleep
def main():
clock = Clock(1,34,12)
while True:
print(clock.show())
sleep(1)
# clock.run()
if __name__ == '__main__':
main()