目录
1 Python 基础
1.1 基本输入、输出
- 输出:
print(输出项列表, sep='分隔符', end='结束符')
print()
函数能输出括号中的内容,默认分隔符为空格sep=' '
,结束符为换行end='\n'
- 括号中 “hello,world” 为字符串类型常量
- python中
单引号''
和双引号""
使用方法相同 - python语句的结束符:
换行
或;
(主要用于多条语句同行) - 不想输出换行符需要在括号中修改默认参数为
end = ""
, 引号中可以是待添加的字符串
print("hello,world") print("hello", "world", sep = ' ', end = '\n') //空格符作为分隔符,换行符作为结束符 print("Hello,", end="my "); print("World"); 输出结果: hello,world hello world Hello,my World
- 输入:
变量 = input("提示信息")
变量 = 变量类型( input("提示信息") )
num = int(input("这有几个苹果:")) print("There are ", end = ""); print(num, " apples"); 输入: 123 //注意:如果输入的不是整数,程序会崩溃 输出结果: There are 123 apples
1.2 列表 list 与 元组 tuple
列表 list
- 列表 list 是 一个可以放置 任意数据类型 的有序集合
list0 = [1, 2, 3.3, 4.44, 'V', "hello", "world"]
print(list0) # [1, 2, 3.3, 4.44, 'V', 'hello', 'world']
- 列表是动态的,长度大小不固定,可以随意地增加、删减或者改变元素
list1 = [1, 2, 3, 4]
list1[3] = 5 # python 中索引同样从 0 开始,list1[0]表示列表中第1个元素
print(list1) # [1, 2, 3, 5]
- 在列表中添加元素时,不会创建新的列表。
list1 = [1, 2, 3, 4]
list1.append(5)
print(list1) # [1, 2, 3, 4, 5]
- 列表 支持 负数索引,-1 表示最后一个元素的索引,-2 表示倒数第二个元素的索引,以此类推(注意:负数索引如果超过了列表的长度,会出现索引溢出的错误)
listA = [1, 2, 3, 4]
print(listA[-1]) # 4
print(listA[-5]) # IndexError: list index out of range
- 列表 支持 切片操作,返回子列表
listA = [1, 2, 3, 4]
sub_list = listA[1:3] # 列表中索引从0到2的子列表,索引切片区间[0,3)
print(sub_list) # [1, 2, 3]
- 列表 支持 嵌套操作
listA = [[1, 2, 3], [4, 5]] # 列表的元素是一个列表
print(listA) # [[1, 2, 3], [4, 5]]
listA = [(1, 2, 3), (4, 5)] # 列表的元素是一个元组
print(listA) # [(1, 2, 3), (4, 5)]
listA[1] = [0, 0] # 列表的元素可以被修改
print(listA) # [(1, 2, 3), [0, 0]]
listA[0][1] = 0 # 列表中元组的元素不能被修改
print(listA) # TypeError: 'tuple' object does not support item assignment
元组 tuple
- 元组 tuple 是 一个可以放置 任意数据类型 的有序集合
tuple0 = (1, 2.2, 'V', "hello")
print(tuple0) # (1, 2.2, 'V', 'hello')
- 元组是静态的,长度大小固定,无法增加删减或者改变
tuple1 = (1, 2, 3, 4)
tuple1[3] = 5
----------------------------------------------------------
Traceback (most recent call last)
~.py in <module>
1 tuple1 = (1, 2, 3, 4)
----> 2 tuple1[3] = 5
TypeError: 'tuple' object does not support item assignment
- 向元组中添加元素时,需要创建一个新的元组,然后把原来的两个元组的值依次填充进去
tup = (1, 2, 3, 4)
new_tup = tup + (5, ) # 创建新的元组 new_tup,并依次填充原元组的值
print(new_tup) # (1, 2, 3, 4, 5)
- 元组 支持 负数索引,-1 表示最后一个元素的索引,-2 表示倒数第二个元素的索引,以此类推(注意:负数索引如果超过了元组的长度,会出现索引溢出的错误)
tup = (1, 2, 3, 4)
print(tup[-1]) # 4(倒数第1个元素)
print(tup[-5]) # IndexError: tuple index out of range
- 元组 支持 切片操作,返回子元组
tup = (1, 2, 3, 4)
sub_tup = tup[1:3] # 元组中索引从1到2的子元组,索引切片区间[1,3)
print(sub_tup) # (2, 3)
- 元组 支持 嵌套操作 (类似 数据结构 中的广义表)
tup = ((1, 2, 3), (4, 5, 6)) # 元组的元素是一个元组
print(tup) # ((1, 2, 3), (4, 5, 6))
tup = ([1, 2, 3], [4, 5, 6]) # 元组的元素是一个列表
print(tup) # ([1, 2, 3], [4, 5, 6])
tup[0][2] = 0 # 元组中列表的元素可以被修改
print(tup) # ([1, 2, 0], [4, 5, 6])
tup[0] = [0, 0, 0] # 元组的元素即使是列表类型,也不可以被修改
print(tup) # TypeError: 'tuple' object does not support item assignment
列表与元组的联系
- 列表 和 元组 可以通过
list()
和tuple()
函数相互转换
listA = [1, 2, 3]
tupleA = (4, 5, 6)
print(tuple(listA)) # (1, 2, 3)
print(list(tupleA)) # [4, 5, 6]
- 列表 和 元组 常用的内置函数
listA = [3, 2, 3, 7, 8, 1]
print( listA.count(3) ) # 2
print( listA.index(8) ) # 4
listA.sort() # list类型自带的排序函数
print(listA) # [1, 2, 3, 3, 7, 8]
print( reversed(listA) ) # <list_reverseiterator object at 0x000001D41FF459D0> 一个迭代器对象的内存地址
print( list(reversed(listA)) ) # [8, 7, 3, 3, 2, 1]
# 另一个排序函数
listA = [3, 2, 3, 7, 8, 1]
print( sorted(listA) ) # [1, 2, 3, 3, 7, 8]
相关问题
python:reversed()后,第二次以后的list()得到的结果都是空 问题
标识符
◆ 作用:表示变量、函数、类、模块等对象的名称
◆ 规则:
由字母、数字、“_”组成,首字符不能是数字
大小写敏感
关键字
◆ Python语言规定了语法含义,如False,class
◆ 查看关键字的方法
>>> help()
Help> keywords
Help> return
预定义标识符
◆ Python语言包含的预定义的内置类、异常、函数等,如
float、input、print。
>>> dir(_ _builtins_ _) # 查看异常名和函数名
保留标识符
◆ “_” 在交互式执行中使用,代表计算结果,如
>>> 100+200 #300
>>> _+200 #500
◆“_ _*_ _” 系统定义的函数名字
_ _new_ _() # 创建新对象的函数
_ _init_ _() # 构造函数
缩进规则
◆ 在代码行前面添加空格或Tab,代表从属关系
◆ 平级的语句行(代码块)的缩进必须相同
◆ 分支、循环、函数定义都采用缩进格式,且末尾有:
注释
# 单行注释
''' 多行注释 ''' """ 多行注释 """
输入
<变量>=input([提示])
例: a=int(input(“请输入整数:”))
b=float(input(“请输入实数:”))
1.3 运算符
算术运算符
◆符号:+, -, *, /,%, //, **
◆数字:全部适用,其中 // 为整除(7//3=2), ** 为指数(2**2=4)
◆字符串:+为两个字符串连接,x*n为复制x n次
lambda
f = lambda x,y,z: x+y*z
print(f(1,2,3)) # 7
if…else 三元表达式
m = a if b else c
# 上下两个表达式等价
if b:
m = a
else:
m = c
运算符优先级(由高到低):
◆函数调用、寻址、下标
◆幂运算 (**)
◆翻转运算符 (~)
◆正负号(+X,-X)
◆算术运算符( *, /,%, //)
◆算术运算符(+, -)
◆位运算符(>>,<<;& , | , ^)
◆关系运算符(<, <=, >, >=, !=, ==)
内置函数
x = -1
abs(x) # 1 绝对值
bool(x) # True 布尔值
complex(x) # (-1+0j) 复数形式
str(x) # -1 字符串
a, b = divmod(7, 3) # 2, 1 商和余数
eval("3+5") # 8 表达式的值
pow(2, 3) # 8 x的y次方
a=[5,2,7]; sorted(a) # [2,5,7] 有序列表
2 控制、循环与函数
2.1 顺序与条件分支控制
2.2 for循环 while循环
格式:for <variable> in range(begin, end, step):\n\t<code>
""" 求1-n之间正整数的平方和 """
n = int(input("input n:"))
sum = 0
for i in range(1, n+1, 1):
sum += i*i
print("sum=", sum)
""" 创建一个3x3的矩阵并输出 """
a = []
for i in range(3):
a.append([])
for j in range(3):
v = int(input("input element:"))
a[i].append(v)
print(a)
# Output1 matrix(normal)
for i in range(len(a)):
for j in range(len(a[i])):
print(a[i][j], end=" ")
print()
# Output2 matrix(for each)
for i in range(a):
for j in range(i):
print(a[i][j], end=" ")
print()
"""【例2-12】寻找自幂数。自幂数:对于n位数,它的各位数字的n次方加起来的和仍等于这个数。如1^3+5^3+3^3=153,153就是一个三位数自幂数
✓ 计算模型:设n位数为k, digit为n位数某位上的值
1) 找n位数自幂数,k取值空间为[10^{n-1} ,10^{n}-1]
2) m=k; digit=m%10; total+=pow(digit,n); m=m//10
3) if m==k: print(k) """
n = int(input("输入位数(1,2,3,4,5,6):"))
while(0 < n < 7):
start = pow(10, n-1)
end = pow(10, n)
print(n, "位自幂数为:")
for k in range(start, end):
m = k
total = 0
while m:
digit = m % 10
total += pow(digit, n)
m //= 10
if(k == total):
print(k, end=' ')
n = int(input("\n输入位数(1,2,3,4,5,6):"))
else:
print("输入位数不在范围内,程序结束!")
2.3 异常
"""【例2-15】
输入两整数,打印它们相除之后的结果
若输入的不是整数或除数为0,进行异常处理
"""
k = 0
while k < 3:
try:
x = int(input("Input the first number:"))
y = int(input("Input the second number:"))
print("x/y=", x/y)
k += 1
except ValueError:
print("Please input a integer!")
except ZeroDivisionError:
print("Divisor cannot be 0!")
"""【例2-18】
求x与y的最大公约数,使用assert语句来约束x、y取值为大于1的正整数
"""
while True:
try:
x = int(input("Input the first number:"))
y = int(input("Input the second number:"))
assert x > 1 and y > 1, "x and y must be bigger than 1"
a = x
b = y
if a < b:
a, b = b, a # swap a and b
while b != 0:
temp = a % b
a = b
b = temp
else:
print("%s and %s 's GCD is %s" % (x, y, a))
break
except Exception as e:
print("Catch an exception:", e)
2.4 函数
2.5 函数式编程
匿名函数 lambda
f = lambda x, y: x + y
print(f(1,2)) # 3
print(f(3,8)) # 11
内嵌函数
在内部函数定义的变量会覆盖外部的同名变量,在离开函数体后失效
def f1():
x = y = 2
def f2():
y = 3 # local variable
print("f2:x=", x) # x=2
print("f2:y=", y) # y=3
f2()
print("f1:x=", x) # x=2
print("f2:y=", y) # y=2
f1()
递归
- 递归求 n ! n! n!: f ( n ) = n ∗ f ( n − 1 ) , n > 1 1 , n = 1 f(n) = ^{1 , n=1} _{n*f(n-1), n>1} f(n)=n∗f(n−1),n>11,n=1
def f(n):
if n == 1:
return 1
return n * f(n - 1)
print(f(4)) # 1*2*3*4 = 24
- 汉诺(Hanoi)塔问题: 借助 B 将 n 个盘子从 A 移到 C = 将 1 个盘子 借助B将n个盘子从A移到C=^{将1个盘子} 借助B将n个盘子从A移到C=将1个盘子
高阶函数
- zip 函数:可以同时遍历多个序列,遍历次数为最短序列长度
- map 函数:可以根据提供的函数对指定序列做映射
- filter(function, iterable):根据函数对给定的可迭代对象进行过滤
from collections import Iterable
a = [1, 2, 3, 4, 5, 6, 7, 8]
even = filter(lambda x: x % 2 == 0, a) # 过滤掉奇数
print(*even) # Output: 2 4 6 8
#print(isinstance(even, Iterable), type(even)) # True <class 'filter'>
s = 0
for item in even:
s += item
print(s) # Output: 20
""" Environment: Pycharm 2021.2.2 Python 3.9
DeprecationWarning: Using or importing the ABCs from 'collections' instead of
from 'collections.abc' is deprecated since Python 3.3, and in 3.10 it will stop working
from collections import Iterable """
函数式编程
自定义高阶函数
3 面向对象程序设计
3.1 类与对象
定义和使用类
- 声明类:
class ClassName:
- 定义类的对象:
ObjectName = ClassName()
- 私有成员变量名:
__privateVarName
class test:
str = "hello" # public variable
__s = "world" # private variable
def output(self):
print(self.str) # Output: hello
print(self._s) # Output: world
def func_t():
t = test() # define the object of the class "test"
print(t.str) # Output: hello
#print(__s) # NameError: name '__s' is not defined.
t.output()
func_t()
- 构造函数:
def __init__(self, 其他参数):
- 析构函数:
def __del__(self):
- 静态函数:在函数上方加
@staticmethod
标记
静态成员和静态方法都是属于类的
静态方法无需传入self
参数,无法访问实例变量
静态放方法可以直接通过类名访问(无需创建对象),也可以通过对象访问
关于静态变量的解释
class test:
str0 = "hi" # static variable
def __init__(self): # constructor
self.str = "hello"
self.__s = "world"
print("Create")
def __del__(self): # destructor
print("Delete")
def output(self):
print(self.str) # Output: hello
print(self.__s) # Output: world
@staticmethod
def staticFunc(): # static method
print("Static")
def func_t():
t = test()
print(t.str0)
print(t.str)
t.output()
t.staticFunc() # ObjectName.staticFuncName()
test.staticFunc() # ClassName.staticFuncName()
func_t()
类的继承
4 网络程序设计
基于TCP/IP协议的网络通信程序
网络通信模型图:
服务器端(线程级):
from socket import *
import threading
name_list = []; client_list = []
s = socket()
s.bind(("127.0.0.1", 30000))
s.listen(20)
def read(s):
try:
return s.recv(2048).decode("utf-8")
except Exception:
print(str(addr) + "Left.")
client_list.remove(s)
def mass_text(s):
try:
while True:
data = read(s)
if data is None:
break
else:
print(data)
for c in client_list:
c.send((str(addr)+"say:"+data).encode("utf-8"))
except Exception:
print("error.")
while True:
conn, addr = s.accept()
client_list.append(conn)
name_list.append(addr)
print(str(addr) + "Joined.")
threading.Thread(target=mass_text, args=(conn,)).start()
s.close()
客户端(线程级):
from socket import *
import threading
s = socket()
s.connect(("127.0.0.1", 30000))
def read(s):
while True:
data = s.recv(2048).decode("utf-8")
print(data)
threading.Thread(target=read, args=(s,)).start()
while True:
data = input(">>")
if data == "exit":
break
s.send(data.encode("utf-8"))
s.close()
Debug
- Pycharm报错:OSError: [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次
原因:windows下python程序占用了该端口号,需要找到占用端口号的进程
方法:打开cmd命令解释器
,输入netstat -aon|findstr "34040"
命令来查询占用端口34040的进程的PID
(见下图),再打开任务管理器 - 详细信息 - PID
找到对应PID的进程并结束任务即可
示例代码
线程级(含客户端界面)
服务器端:
from socket import *
import threading
import sys
from datetime import *
name_list = []
client_list = []
s = socket()
s.bind(("127.0.0.1", 30000))
s.listen(20)
def writeLog(Str): # 写日志
try:
log_writer = open('log.txt', 'a+') # 加入服务器日志
log_writer.write(Str + "\n")
except Exception:
print("write log error")
def read(s, name):
try:
return s.recv(2048).decode("utf-8")
except Exception:
Str = datetime.now().strftime('%Y.%m.%d %H:%M:%S')+ " " +name+" Left."
print(Str)
for cl in client_list:
cl.send(Str.encode("utf-8"))
writeLog(Str)
name_list.remove(name)
client_list.remove(s)
def mass_text(s, name):
try:
while True:
data = read(s, name)
if data is None:
break
else:
Str = datetime.now().strftime('%Y.%m.%d %H:%M:%S')+" "+name+": "+data
print(Str)
for cl in client_list:
cl.send(Str.encode("utf-8"))
writeLog(Str)
except Exception:
print("")
while True:
conn, addr = s.accept()
client_list.append(conn)
name = conn.recv(2048).decode("utf-8")
if name in name_list:
continue
name_list.append(name)
Str = datetime.now().strftime('%Y.%m.%d %H:%M:%S')+" "+name+" Joined."
print(Str)
writeLog(Str)
threading.Thread(target=mass_text, args=(conn, name,)).start()
sys.exit()
客户端:
from socket import *
from tkinter import *
import threading
import sys
s = socket()
s.connect(("127.0.0.1", 30000))
def sendText(): # 点击按钮,发送信息
data = text2.get(1.0, "insert")
# print("$"+data+"$")
if data == "#exit":
s.close()
text2.delete(1.0, "end")
sys.exit(1)
s.send(data.encode("utf-8"))
# text1.insert("end", "You send:" + data + "\n") # 显示文本
text2.delete(1.0, "end") # 发送后清空输入栏
tk = Tk() # GUI
tk.title("聊天室")
# f = Frame(tk)
tk.geometry("460x380")
tk.attributes("-alpha", 0.8)
label = Label(tk, text="聊天内容", width=60)
label.place(x=20, y=5)
text1 = Text(tk, width=60, height=20)
text1.place(x=20, y=30)
text2 = Text(tk, width=50, height=3)
text2.place(x=20, y=320)
b = Button(tk, text="发送", command=sendText, width=8, height=2)
b.place(x=380, y=320)
def read(s): # 接收服务器发送的信息
while True:
sdata = s.recv(2048).decode("utf-8")
print(sdata)
text1.insert("end", sdata + "\n")
threading.Thread(target=read, args=(s,)).start()
tk.mainloop()
进程级
服务器端:
from socket import *
from multiprocessing import Process
def talk(conn, addr):
while True:
try:
cmsg = conn.recv(1024)
if not cmsg:
break
conn.send(cmsg.upper())
except Exception:
break
conn.close()
if __name__ == "__main__":
print("主程序开始")
server = socket()
ip_port = ("127.0.0.1", 8080)
server.bind(ip_port)
server.listen(20)
while True:
conn, caddr = server.accept()
print("Connect from: ", caddr)
# 把连接加入进程管理池,talk函数处理连接,args为连接内容
p = Process(target=talk, args=(conn, caddr))
p.start() # 开启进程
server.close()
客户端:
# 进程级客户端
from socket import *
client = socket()
ip_port = ("127.0.0.1", 8080)
client.connect(ip_port)
while True:
data = input(">>").strip()
if not data:
continue
client.send(data.encode("utf-8"))
smsg = client.recv(1024)
print("Server return: ", smsg.decode("utf-8"))
client.close()
非进程/线程
服务器端:
from socket import *
from time import ctime
host = ""
port = 4700
buf_size = 1024
addr = (host, port)
s = socket(AF_INET, SOCK_STREAM, 0) # socket object
s.bind(addr) # 绑定地址
s.listen(20) # 监听端口,控制连接数量
print("等待客户连接...\r\n")
cs, caddr = s.accept() # 接收客户端发来的请求
print("...连接来自于: ", caddr)
data = "欢迎你的到来!\r\n"
cs.sendall(bytes(data, "utf-8")) # 向客户端发送欢迎词
while True:
# 接受客户端发送的信息
data = cs.recv(buf_size).decode("utf-8") # 设置缓冲区,编码
if not data:
break
data = "[%s]%s\r\n" % (ctime(), data) # 服务器端回复数据的内容
cs.sendall(bytes(data, "utf-8")) # 向客户端发送欢迎词
print(data)
cs.close()
s.close()
客户端:
from socket import *
buf_size = 1024
addr = ("127.0.0.1", 4700) # 服务器地址: ip地址+端口号
# 多台机器则不能为127.0.0.1(即localhost)
cs = socket(AF_INET, SOCK_STREAM, 0) # socket object
cs.connect(addr) # 向Server发送连接请求
data = cs.recv(buf_size).decode("utf-8") # 接受Server传送的信息
if data:
print(data)
# 与Server交互
while True:
data = input()
if data:
cs.sendall(bytes(data, "utf-8")) # encode and send it to Server
data = cs.recv(buf_size).decode("utf-8")
if data:
print(data)
cs.close()
实验
参考资料:
Python编写多线程多人聊天室系统(Socket编程、tkinter组件使用)
TCP协议的通信小程序与函数接口
5 图形界面编程
python按钮调用函数_如何在Tkinter中将参数传递给Button命令?
Python-解决Tkinter按钮类似组件Command的传参问题
python按钮调用函数_如何在Button的command中传递参数?
让窗口右上角关闭按钮‘X’失效