学习路线&进度记录
学习路线(待整理)
先记录,最后整理
初阶
介绍 | 简明 Python 教程 (gitbooks.io)
进阶
Python Cookbook 3rd Edition Documentation — python3-cookbook 3.0.0 文档
进度记录
- 20201103
读完《简明教程》,没有总结
- 20221108
最近在读《python编程快速上手》,没有读完,这本书的好处在于,可能对知识的覆盖不是太全面,但是十分接近于实际应用
2、另一个,廖雪峰的书籍,覆盖比较全面,涉及到边边角角的知识,暂时全力看这一个
基础知识框架整理
一些其它
-
命令行参数的传入
-
源文件的字符编码
-
文档字符串2.7. 函数 | 正文 |《Python 简明教程 2018》| Python 技术论坛 (learnku.com)
基本数据类型
整型
浮点型
复数
字符串(单独开一章)
字符串
一些特性
- 不可变(关于replace方法的理解)使用dict和set - 廖雪峰的官方网站 (liaoxuefeng.com)
- 自动级联
- 利用
\
表示同一行
几种表达形式
- 单引号
- 双引号
- 前缀字符
r' '
----->表示其中的字符不转义 - 三引号---->解决多行问题以及,以及文档字符串
特殊字符
- 转义字符```
- 引号的区分
前缀
- 自然字符串–>
r R
- unicode字符—>
u U
- byte类型的数据---->
b'ABC'
一些操作
格式化输出
字符串和编码 - 廖雪峰的官方网站 (liaoxuefeng.com)
format方法—对字符串进行格式化处理
2.4. 基本语法 | 正文 |《Python 简明教程 2018》| Python 技术论坛 (learnku.com)
##参考例子
整数 = 1
整数 = 100
整数 = -8080
整数 = 0
十六进制写法 = 0xff00
十六进制写法 = 0xa5b4c3d2
分隔号写法 = 10_000_000_000
分隔号写法 = 0x_a1b2_c3d4
浮点数 = 1.23
浮点数 = 3.14
浮点数 = -9.01
科学计数法 = 1.23e9
科学计数法 = 12.3e8
科学计数法 = 1.2e-5
字符串 = 'abc'
字符串 = "xyz"
字符串 = "I'm OK"
转义符号 = 'I\'m \"OK\"!'
转义符号 = 'I\'m learning\nPython.'
转义符号 = '\\\t\\'
强制不转义 = r'\\\t\\'
多行字符串 = '''line1
line2
line3'''
布尔值 = True
布尔值 = False
布尔值 = 3 == 2 + 1
布尔值 = 3 > 2
布尔值 = 3 > 5
布尔值运算 = True and True
布尔值运算 = True or False
布尔值运算 = not False
布尔值运算 = 3 == 2 + 1 and 3 > 2 or not 3 > 5
空值 = None
# 变量
a = 'ABC'
b = a
a = 'XYZ'
# a 是 'XYZ', b 是 'ABC'
# 常量 (全部字母大写)
PI = 3.14159265359
# 运算
10 / 3 # 小数除法: 3.3333333333333335
10 // 3 # 整数除法: 3
10 % 3 # 取余: 1
关于编码知识的总结
utf-8与unicode
- 在存储与传输中,使用的utf-8
- 在使用时(装载到内存中进行编辑时)采用的是unicode
字符串的两种视角
- unicode编码——
x='abc'
——可以通过编码encode
编码为指定的bytes——len()表示的是字符数 - byte字节流——
X =b'abc'
——可以通过decode
按照不同的形式进行解码——len()表示的是字节数
具体的使用见
字符串和编码 - 廖雪峰的官方网站 (liaoxuefeng.com)
格式化输出
参考见上
-
利用
%s
-
format()
-
f-string
运算符与表达式
只记一些比较特殊的
数学运算符
-
乘方——
**
-
除法
/
非整除//
整除
布尔运算符
- and
- or
- not
流程控制
判断
- if-else
- elif
- elif 一旦被执行,就跳过剩下所有语句
- 所以次序很重要
- 可以省略else
if name == "Alice":
print("hi, Alice")
elif age < 12:
print("you're not Alice, kiddo")
备注
当使用input时,注意input的返回值为字符串类型
##false
birth = input('birth: ')
if birth < 2000:
print('00前')
else:
print('00后')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: str() > int()
##true
s = input('birth: ')
birth = int(s)
if birth < 2000:
print('00前')
else:
print('00后')
循环
- while
- 可以有一个else语句
- for…in 循环
- 常与range函数搭配
- range()可以指定步长
- 同样可以跟一个else语句
# while
number = 23
running = True
while running:
guess = int(input('Enter an integer : '))
if guess == number:
print('Congratulations, you guessed it.')
# 这会导致 while 循环停止
running = False
elif guess < number:
print('No, it is a little higher than that.')
else:
print('No, it is a little lower than that.')
else:
print('The while loop is over.')
# 你可以在此处继续进行其它你想做的操作
print('Done')
# for
for i in range(1, 5, 2):
print(i)
else:
print('The for loop is over')
- 备注
- 在遍历同一个集合时修改该集合的代码可能很难获得正确的结果。通常,更直接的做法是循环遍历该集合的副本或创建新集合
# Strategy: Iterate over a copy
for user, status in users.copy().items():
if status == 'inactive':
del users[user]
# Strategy: Create a new collection
active_users = {}
for user, status in users.items():
if status == 'active':
active_users[user] = status
break与continue
- 与c语言一致
sys包中的sys.exit()——可以用来提前停止程序
函数
作用域(全局变量&局部变量)与gloal标识符
- 可以在函数内使用
global
修饰一个变量,表明此变量为全局变量
x = 50
def func():
global x
print('x is', x)
x = 2
print('Changed global x to', x)
func()
print('Value of x is', x)
#运行结果
python function_global.py
x is 50
Changed global x to 2
Value of x is 2
空函数
- pass不能省略,会报错
def nop():
pass
参数——默认参数值、关键字参数、可变参数
-
默认参数值
- 只有形参列表末尾的参数才能指定默认值
- 坑——默认参数必须指向不变对象!函数的参数 - 廖雪峰的官方网站 (liaoxuefeng.com)
-
可变参数
- 单星号——收录到元组中
-
关键字参数
- 双星号——收录到字典中
- 命名关键字参数——限制关键字的名字
- 函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符
*
- 名关键字参数必须传入参数名
- 可以有缺省值,从而简化调用
- 函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符
-
参数组合
- 参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
#默认参数值
def say(message, times=1):
print(message * times)
say('Hello')
say('World', 5)
$ python function_default.py
Hello
WorldWorldWorldWorldWorld
#可变参数
def total(a=5, *numbers, **phonebook):
print('a', a)
# 遍历元组中的所有项
for single_item in numbers:
print('single_item', single_item)
# 遍历字典中的所有项
for first_part, second_part in phonebook.items():
print(first_part,second_part)
print(total(10,1,2,3,Jack=1123,John=2231,Inge=1560))
$ python function_varargs.py
a 10
single_item 1
single_item 2
single_item 3
Inge 1560
John 2231
Jack 1123
None
##关键子参数
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
>>> person('Michael', 30)
name: Michael age: 30 other: {}
>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
##命名关键字参数
def person(name, age, *, city, job):
print(name, age, city, job)
>>> person('Jack', 24, city='Beijing', job='Engineer')
Jack 24 Beijing Engineer
可返回多个值
- 本质返回单一的值,存放在tuple中
import math
def move(x, y, step, angle=0):
nx = x + step * math.cos(angle)
ny = y - step * math.sin(angle)
return nx, ny
return与None
- 当无retuan语句时,返回
None
- print无return语句
spam = print("hello")
print(spam == None)
True
数据结构
参考
《python编程快速上手》
序列式
序列数据类型包括列表、字符串、由range()返回的范围对象,以及元组
其共同的一些操作,包括——按索引取值、切片、for循环、len()、in、not in
列表list
底层思想
- 引用----->浅拷贝
- list里面的元素的数据类型也可以不同
- 一些待补充❓
相关操作
- 索引(可以为负数)
- 切片
- len()
- 连接与复制(+、*)
- 删除del、pop(i)–默认为末尾
- in 和 not in
- 循环
相关方法
- index(重复时,只操作第一个)
- append&insert
- remove(重复时,只操作第一个)
- pop(i)——>不指定索引,默认为末尾元素
- sort(按ASCII字符顺序;可指定
revese
、key
关键字) - reverse
一些相关函数
- enumerate()——返回索引与值
- random.choice()——随机选择
- random.shuffle()——就地排序(打乱排序)
spam = ['cat', 'bat', 'rat', 'elephant']
#####相关操作
# 索引(可以为负数)
spam[1]
spam[-1]
# 切片
spam[1:4]
#len()
len(spam)
#连接与复制(+、*)
spam = spam + ['A', 'B']
spam = spam *3
#删除del
del spam[2]
# in 和 not in
'cat' in spam
'cat' not in spam
# 循环
for item in spam:
print(item, end=' ')
##一个
for i in range(len(spam)):
print('index' + str(i) + 'in spam is :' + spam[i] )
###### 相关方法
#index
spam.index('cat')//1
# append&insert
spam.append('mouse')
spam.insert(1,'chicken')
#remove
spam.remove('cat')
#sort(按ASCII字符顺序,可指定`revese`关键字)
spam.sort()
spam.sort(reverse = True)
spam.sort(key = str.lower)
# reverse
spam.reverse()
###### 一些相关函数
#enumerate()
for index, item in enumerate(spam):
print('index' + str(i) + 'in spam is :' + spam[i] )
#random.choice()
random.choice(spam)
#random.shuffle()
random.shuffle(spam)
元组tuple(不可变的列表 )
- 与列表区分
- 与列表间的相互转换
list()
和tuple
- 一个小“bug",可变的tuple使用list和tuple - 廖雪峰的官方网站 (liaoxuefeng.com)
tuple(['cat', 'dog', 5])
list(('cat', 'dog', 5))
字典dictionary(键值对)
相关操作
-
索引
-
添加
-
in
¬ in
——相应的键key是否存在
方法
-
key()——注意返回的不是列表,不可改变
-
values()——注意返回的不是列表,不可改变
-
items()——注意返回的不是列表,不可改变
-
get()——检查是否存在相应的键key,若不存在可以指定返回的备用值
-
setdefault()——为某一个键设置一个默认值
-
pop(key)——删除
技巧
- 避免key不存在
in
¬ in
——相应的键key是否存在- get()——检查是否存在相应的键key,若不存在可以指定返回的备用值
spam = {'name': 'zophie', 'age': 7}
###### 相关操作
# 索引
spam['name']
# 添加
spam['sex'] = 'man'
# `in`&`not in`
if 'name' in spam:
print(spam['name'])
###### 方法
# keys()
for k in spam.keys():
print(v)
# values()
for v in spam.values():
print(v)
# items()
for k,v in spam.items():
print(v)
# get()
spam.get('set', 0)
# setdefault()
spam.setdefault('sex', 'man')
非序列式
集合set
- 定义时,要提供一个list作为输入集合
- key不重复
相关操作
- i
n
¬ in
方法
- copy()
- add()
- issuperset()
- remove
- 求并集&
>>> bri = set(['brazil', 'russia', 'india'])
>>> 'india' in bri
True
>>> 'usa' in bri
False
>>> bric = bri.copy()
>>> bric.add('china')
>>> bric.issuperset(bri)
True
>>> bri.remove('russia')
>>> bri & bric # 或者是 bri.intersection(bric)
{'brazil', 'india'}
一些易混淆
# 定义的区分
## list
shoplist = ['apple', 'mango', 'carrot', 'banana']
##元组(圆括号可选)
zoo = ('python', 'elephant', 'penguin')
###空元组
myempty = ()
###单元组(必须在且仅在第一个项的后面用一个逗号来指定该元组)
singleton = (2 , )
##字典
ab = {
'Swaroop': 'swaroop@swaroopch.com',
'Larry': 'larry@wall.org',
'Matsumoto': 'matz@ruby-lang.org',
'Spammer': 'spammer@hotmail.com'
}
## 集合(要创建一个set,需要提供一个list作为输入集合)
s = set([1, 2, 3])
高级特性
- 切片
- 迭代
- 列表生成式
- 生成器
- 迭代器
用到时,再查迭代器 - 廖雪峰的官方网站 (liaoxuefeng.com)
关于iterable类型与iteerator类型
凡是可作用于for
循环的对象都是Iterable
类型;
凡是可作用于next()
函数的对象都是Iterator
类型,它们表示一个惰性计算的序列;
集合数据类型如list
、dict
、str
等是Iterable
但不是Iterator
,不过可以通过iter()
函数获得一个Iterator
对象。
列表生成式
用于简化列表的生成,并可对列表中的元素进行操作,以及使用if语句进行判断
>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]
# 使用两层循环,可以生成全排列
>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
#使用两个变量来生成list
>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> [k + '=' + v for k, v in d.items()]
['y=B', 'x=A', 'z=C']
生成器
参考
[(219条消息) python(列表生成式/器)_huo_1214的博客-CSDN博客](https://blog.csdn.net/huo_1214/article/details/79209893#:~:text=python (列表生成式%2F器) 1 %23列表生成式是快速生成一个列表的一些公式 2 numbers %3D [],in range ( 0%2C 101 )] More items)
- 不必创建完整的列表,一边循环一边计算
- 两种定义方法
- 把一个列表生成式的
[]
改成()
- 如果一个函数定义中包含
yield
关键字,那么这个函数就不再是一个普通函数,而是一个generator函数,调用一个generator函数将返回一个generator:
- 把一个列表生成式的
- generator 函数的使用
- 首先要生成一个generator对象,然后用
next()
函数不断获得下一个返回值 - 函数改成generator函数后,我们基本上从来不会用
next()
来获取下一个返回值,而是直接使用for
循环来迭代: - 调用generator函数会创建一个generator对象,多次调用generator函数会创建多个相互独立的generator
- 首先要生成一个generator对象,然后用
- generator 函数的执行流程
- 在每次调用
next()
的时候执行,遇到yield
语句返回,再次执行时从上次返回的yield
语句处继续执行。
- 在每次调用
#创建
#1
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>
#2
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>
#打印方式一
>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
25
>>> next(g)
36
>>> next(g)
49
>>> next(g)
64
>>> next(g)
81
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
打印方式二
>>> g = (x * x for x in range(10))
>>> for n in g:
... print(n)
异步IO
模块与包
模块与包的理解
-
一个包含很多方法和变量并以
.py
为扩展的文件。(每一个pyhon文件就是一个模块) -
聚合——可以将不同模块聚合为包,也可以将不同包聚合为一个更高层的包,在文件中包表示为含有——init.py文件的目录,该文件可以执行包的初始化代码,或设置
_all_
变量(列表——可用于显性指示导入哪些子模块,当从包中导入``*`时) -
包是一种用“点式模块名”构造 Python 模块命名空间的方法。例如,模块名
A.B
表示包A
中名为B
的子模块。正如模块可以区分不同模块之间的全局变量名称一样,点式模块名可以区分 NumPy 或 Pillow 等不同多模块包之间的模块名称。
字节码文件
- python运行原理(解释性)——解释器会将源程序转换成一种被称为字节码
.pyc
的中间形式,然后将字节码转换成你的计算机的机器语言,然后运行它 - 了快速加载模块,Python 把模块的编译版缓存在
__pycache__
目录中,文件名为module.*version*.pyc
模块的检索与sys.path
- 首先搜索具有该名称的内置模块,模块的名字被列在
sys.builtin_module_names
- 然后在变量
sys.path
给出的目录列表中搜索- sys.path从以下位置初始化
- 输入脚本的目录(或未指定文件时的当前目录)。
PYTHONPATH
(目录列表,与 shell 变量PATH
的语法一样)。- 依赖于安装的默认值(按照惯例包括一个
site-packages
目录,由site
模块处理)。
- sys.path从以下位置初始化
导入格式
- 模块
import [模块名]
#导入所有不以下划线(_)开头的名称,一般不用
from [模块名] import *
from [模块名] import [具体的变量或是函数名]
from [模块名] as [别名]
from [模块名] import [具体的变量或是函数名] as [别名]
- 包
- 基本同上,但有一些地方比较模糊,暂时够用
- 以脚本形式执行脚本
关于模块的定义与_name_
-
每一个python模块都定义了各自的
_name_
,可以通过这个让模块在被导入和独立运行时执行不同的操作 -
举例
#!/usr/bin/env python3#第1行注释可以让这个hello.py文件直接在Unix/Linux/Mac上运行
# -*- coding: utf-8 -*-#第2行注释表示.py文件本身使用标准UTF-8编码;
' a test module '
__author__ = 'Michael Liao'
import sys
def test():
args = sys.argv
if len(args)==1:
print('Hello, world!')
elif len(args)==2:
print('Hello, %s!' % args[1])
else:
print('Too many arguments!')
##此if语句当一个模块通过命令行运行时执行一些额外的代码,最常见的就是运行测试。
if __name__=='__main__':
test()
关于作用域问题
使用模块 - 廖雪峰的官方网站 (liaoxuefeng.com)
后面再补充
- 类似
__xxx__
这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如上面的__author__
,__name__
就是特殊变量,hello
模块定义的文档注释也可以用特殊变量__doc__
访问,我们自己的变量一般不要用这种变量名; - 类似
_xxx
和__xxx
这样的函数或变量就是非公开的(private),不应该被直接引用,比如_abc
,__abc
等;
输入与输出
错误和异常
函数式编程
面向对象
核心思想
IO编程
异步IO与同步IO
异步复杂性高
- 回调模式
- 轮询模式
文件IO
文件路径问题
文件路径
参考
[(219条消息) Python I/O(读写)详解 文件路径][绝对路径][相对路径][打开指定文件][读写文件][关闭指定文件]_码农阿杰的博客-CSDN博客_python 读取文件的绝对路径
(219条消息) 关于python文件读写的路径问题_永不落后于人的博客-CSDN博客_python要读取的文件放在哪里
windows下的路径
-
window下以
\
为分隔符 -
当用字符串表示相关路径时,又涉及到转义字符问题,如
c:\\bacon
-
在用pathlib包中的一些函数,返回的window下的路径可能表示为
/
,只是类似于linux
pathlib与os
-
对路径进行操作
-
消除了不同系统的路径表示差异
-
以Path对象为基础
-
os版本较老
-
不再细写
功能 | pathlib | os |
---|---|---|
Parh(’spam‘,’bacon’, ‘eggs’)///Path(‘spam’) /‘bacon’ / ‘eggs’ | ||
Path.cwd()//Path.home() | ||
Path(r’“c:\users\A1\spam”).mkdir | ||
path = Path(r’“c:\users\A1\spam”); path.is_absolute |
os及os.path模块
思想
- 对于路径当作字符串进行处理
- 由于os的区别,便于移植,拼接分割,采用特定的函数进行处理
- 相对路径与绝对路径,不太清楚如何处理的,不过可以采用相对路径的方式
# 查看
os.path.abspath('.')#当前路径,一些补充见下文
#路径的拼接与拆解
>>> os.path.join('/Users/michael', 'testdir')
'/Users/michael/testdir'
>>> os.path.split('/Users/michael/testdir/file.txt')
('/Users/michael/testdir', 'file.txt')
>>> os.path.splitext('/path/to/file.txt')
('/path/to/file', '.txt')
#目录的创建与删除
# 然后创建一个目录:
>>> os.mkdir('/Users/michael/testdir')
# 删掉一个目录:
>>> os.rmdir('/Users/michael/testdir')
文件的重命名与删除
# 对文件重命名:
>>> os.rename('test.txt', 'test.py')
# 删掉文件:
>>> os.remove('test.py')
#拷贝见shutil模块
参考
os.getcwd && os.path.abspath详解https://blog.csdn.net/funnypython/article/details/787
文件读写
标准流程
#读文件
#打开
file = open(file_name, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
#读取
file.read()## 一次读取全部内容
file.read(size) # 每次最多读取size个字节的内容
file.readline() # 每次读取一行内容
file.readlines() #一次读取所有内容并按行返回list,一般用于读取配置文件
for line in file.readlines():
print(line.strip()) # 把末尾的'\n'删掉
#关闭
file.close()
#异常处理版本
try:
f = open('/path/to/file', 'r')
print(f.read())
finally:
if f:
f.close()
#with语句,自动调用close方法
with open('/path/to/file', 'r') as f:
print(f.read())
#写文件
f = open('/Users/michael/test.txt', 'w')
f.write('Hello, world!')
f.close()
文件读写格式等见链接
- [(219条消息) python-文件方法(读写)_不侠居的博客-CSDN博客_python 读写文件](https://blog.csdn.net/m0_46778548/article/details/121201868#:~:text=python-文件方法(读写) 1 1.文件对象 在python中用 open () 可以创建一个文件对象。 open,3.1读 有三个方法可以使用 file.read ( [size]) 从文件读取指定的字节数,如果未给定或为负则读取所有。 例1: )
内存空间IO
stringIO
#写入
#导入
from io import StringIO
f = StringIO()
f.write('hello')
print(f.getvalue())
#读取
from io import StringIO
f = StringIO('Hello!\nHi!\nGoodbye!')
while True:
s = f.readline()
if s == '':
break
print(s.strip())
Hello!
Hi!
Goodbye!
BytesIO
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U2d8iRpU-1675080472174)(./python_%E7%AC%94%E8%AE%B0_20221103.assets/image-20230127151750145.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KpFzlEkb-1675080472175)(./python_%E7%AC%94%E8%AE%B0_20221103.assets/image-20230127151758944.png)]
异步IO
- 同步IO必须等待IO
- 当遇到IO操作时,代码只负责发出IO请求,不等待IO结果,然后直接结束本轮消息处理,进入下一轮消息处理过程。当IO操作完成后,将收到一条“IO完成”的消息,处理该消息时就可以直接获取IO操作结果。
参考
Python 高级编程之协程和异步 IO - CodeAntenna
有些复杂,建议后面搭配python-cookbook的书看一下
简单总结几种IO方式
总体来说,分为同步IO和异步IO,两者的区别在于——进程是否等待IO操作完成
同步IO又分为阻塞式与非阻塞式,区别在于调用函数时,当前线程是否被挂起,在阻塞式中,最基础的是轮询的方式,使用while循环,在这基础之上,又发展出IO复用的方式,具体有select ,poll,epoll等,核心在于一个线程监听,当监听到时,交给其它线程进行处理
有点不太对,几种方式可以看作是递进的方式
协程
网络编程
TCP编程
客户端
import socket
s = socket.socket(socket.AF_INET, socket.SOCk_STREAM)
s.connect(('www.sina.com.cn', 80))
s.send(b'GET / HTTP/1.1\r\nHost:www.sina.cn\r\nConnection: close\r\n\r\n')
buffer = []
while True:
d = s.recv(1024)
if d:
buffer.append(d)
else:
break
data = b''.join(buffer)
s.close()
header, html = data.split(b'\r\n\r\n', 1)
print(header.decode('utf-8'))
with open('sina.html', 'wb') as f:
f.write(html)
服务端
s = socket.socket(socket.AF_INET, socket.SOCK_Stream)
s.bind(('127.0.0.1', 9999))
s.listen(5)
print('Waiting for connection...')
while True:
sock, addr = s.accept()
t = threading.Thread(target = tcplink, args = (sock, addr))
t.start()
def tcplink(sock. addr):
print('Accept new connection from %s : %S...' %addr)
sock.send(b'Welcome')
while True:
data = sock.recv(1024)
time.sleep(1)
if not dada or data.decode ('utf-8') == "exit":
break
sock.send('Hello, %s!' %data.decode('utf-8').encode('utf-8'))
sock.close()
print("Conection from %s:%s closed" %addr)
测试
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接:
s.connect(('127.0.0.1', 9999))
# 接收欢迎消息:
print(s.recv(1024).decode('utf-8'))
for data in [b'Michael', b'Tracy', b'Sarah']:
# 发送数据:
s.send(data)
print(s.recv(1024).decode('utf-8'))
s.send(b'exit')
s.close()
UDP编程
服务器
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind('127.0.0.1', 9999)
print('Bind UDP on 9999...')
while True:
data, addr = s.recvfrom(1024)
print('recvived from %s :%s.' %addr)
s.sendto(b'Hello, %s!' %data, addr)
客户端
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for data in [b'Michael', b'Tracy', b'Sarah']:
s.sendto(data, ('127.0.0.1', 9999))
print (s.recv(1024).decode('utf-8'))
s.close()
随记
关于sys.path与sys.argv
-
sys.argv——保存有命令行参数的字符串 列表
- sys.argv[0]`中存放着当前运行的模块名
-
sys.path 是模块导入时要搜索的目录列表。
- sys.path 的第一个字符串是空的,表示当前目录也是 sys.path 的一部分,与 PYTHONPATH 环境变量是相同的
关于python3 range()
- Python3 range() 函数返回的是一个可迭代对象(类型是对象),而不是列表类型, 所以打印的时候不会打印列表
- Python3.x 中 range() 函数返回的结果是一个整数序列的对象,而不是列表。
- Python3 list() 函数是对象迭代器,可以把range()返回的可迭代对象转为一个列表,返回的变量类型为列表。
Python3 range() 函数用法 | 菜鸟教程 (runoob.com)
lambda函数
- 小的匿名函数
见Python Lambda (w3school.com.cn)
python网络编程
- 在套接字中,使用的是元组
交互模式输入多行代码
(219条消息) Python交互模式如何进行多行输入(3.8.1版本)_坤舆小菜鸡的博客-CSDN博客
4).decode(‘utf-8’))
s.send(b’exit’)
s.close()
#### UDP编程
服务器
~~~python
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind('127.0.0.1', 9999)
print('Bind UDP on 9999...')
while True:
data, addr = s.recvfrom(1024)
print('recvived from %s :%s.' %addr)
s.sendto(b'Hello, %s!' %data, addr)
客户端
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for data in [b'Michael', b'Tracy', b'Sarah']:
s.sendto(data, ('127.0.0.1', 9999))
print (s.recv(1024).decode('utf-8'))
s.close()
随记
关于sys.path与sys.argv
-
sys.argv——保存有命令行参数的字符串 列表
- sys.argv[0]`中存放着当前运行的模块名
-
sys.path 是模块导入时要搜索的目录列表。
- sys.path 的第一个字符串是空的,表示当前目录也是 sys.path 的一部分,与 PYTHONPATH 环境变量是相同的
关于python3 range()
- Python3 range() 函数返回的是一个可迭代对象(类型是对象),而不是列表类型, 所以打印的时候不会打印列表
- Python3.x 中 range() 函数返回的结果是一个整数序列的对象,而不是列表。
- Python3 list() 函数是对象迭代器,可以把range()返回的可迭代对象转为一个列表,返回的变量类型为列表。
Python3 range() 函数用法 | 菜鸟教程 (runoob.com)
lambda函数
- 小的匿名函数
见Python Lambda (w3school.com.cn)
python网络编程
- 在套接字中,使用的是元组
交互模式输入多行代码