您现在的位置是:网站首页> PY&Rust
Python基本语法笔记
- PY&Rust
- 2024-09-08
- 839人已阅读
Python基本语法笔记
py文件想做成本地库,在本机任何一个文件中直接import,怎么实现?
Python常见的文件类型介绍
.py python的源代码文件,可以直接编辑,直接运行
.pyc Python源代码import后,编译生成的字节码
.pyd Python的动态链接库(Windows平台dll),需要通过其它程序调用运行。
.ipynb ipynb就是ipythonnotebook,是由jupyter插件生成的文件
Pycharm是一款流行的Python IDE,具有强大的代码编辑、调试和版本控制功能,因此,Pycharm作为Jupyter Notebook的替代品成为了一种趋势。在本文中,我们将从多个角度分析如何在Pycharm中运行ipynb文件。
1. 安装必要的插件
在Pycharm中运行ipynb文件之前,我们需要安装必要的插件。打开Pycharm,点击“File”-“Settings”-“Plugins”,搜索“Jupyter”,安装“Jupyter Notebook Integration”插件。此外,还需要安装“Python Scientific”插件,以便在Pycharm中使用科学计算库。
2. 导入ipynb文件
导入ipynb文件后,我们可以在Pycharm中直接编辑和运行代码。在Pycharm的“Project”视图中,右键单击要导入的文件夹,选择“New”-“Jupyter Notebook”,即可创建一个新的ipynb文件。然后,我们可以通过拖放或复制粘贴的方式将ipynb文件从Jupyter Notebook中导入到Pycharm中。
3. 运行ipynb文件
在Pycharm中运行ipynb文件有两种方法。一种是在Pycharm中打开ipynb文件,然后点击“Run”按钮。这将启动一个新的Jupyter Notebook服务器,并在默认浏览器中打开该文件。另一种方法是使用Pycharm的“Python Console”功能。在Pycharm中打开ipynb文件后,我们可以在“Python Console”中执行代码。要在“Python Console”中运行ipynb文件,请先选择“Cell”-“Run All”或“Cell”-“Run Selected Cell(s)”,然后在“Python Console”中查看结果。
4. 配置Pycharm与Jupyter Notebook服务器
我们还可以将Pycharm与现有的Jupyter Notebook服务器连接起来,以便在Pycharm中编辑和运行代码。要实现这一点,我们需要在Pycharm的“Settings”中配置远程服务器。首先,我们需要在Jupyter Notebook服务器上设置一个密码,然后在Pycharm中选择“File”-“Settings”-“Project:xxxx”-“Project Interpreter”-“Add”-“SSH Interpreter”。在这里,我们需要配置服务器的IP地址、用户名和密码。配置完成后,我们可以在Pycharm中直接连接到Jupyter Notebook服务器,并在Pycharm中编辑和运行代码。
init.py文件
__init__.py 文件在 Python 包中扮演着重要的角色,它标识一个目录为包,并允许你执行初始化操作、导入模块以及定义包级别的变量和函数
首先执行该文件里的内容
py文件想做成本地库,在本机任何一个文件中直接import,怎么实现?
通常,一个Python库至少包含一个__init__.py文件,这个文件可以为空,但它的存在告诉Python这个目录应该被视为一个包。
mylib/
│
├── __init__.py
├── module1.py
└── module2.py
编写setup.py接下来,你需要一个setup.py文件,这是Python包的安装脚本。这个文件会告诉Python你的库需要哪些依赖,以及如何安装它。from setuptools import setup, find_packages
setup(
name='mylib',
version='0.1',
packages=find_packages(),
install_requires=[
# 依赖列表
],
)
安装库
有了setup.py,你就可以安装你的库了。在库的根目录下运行:pip install .或者,如果你想在开发时即时反映代码更改,可以使用:pip install -e .这样,你的库就被安装到本地了,可以在任何地方import。
如何在任何地方使用?一旦安装完成,你就可以在任何Python脚本中import你的库了。
from mylib.module1
import some_function
Python3包
什么是包
包就是一个包含__init__.py文件的文件夹,文件夹内可以包含子包或者模块
ui_hello.py内容
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
class Ui_Form(object):
def setupUi(self, Form):
if not Form.objectName():
Form.setObjectName(u"Form")
Form.resize(400, 300)
self.label = QLabel(Form)
self.label.setObjectName(u"label")
self.label.setGeometry(QRect(120, 80, 54, 12))
self.retranslateUi(Form)
QMetaObject.connectSlotsByName(Form)
# setupUi
def retranslateUi(self, Form):
Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None))
self.label.setText(QCoreApplication.translate("Form", u"TextLabel", None))
基本语法
注释代码:
# 第一个注释
# 第二个注释
'''
第三注释
第四注释
'''
"""
第五注释
第六注释
"""
print ("Hello, Python!")
行与缩进
python最具特色的就是使用缩进来表示代码块,不需要使用大括号 {} 。
缩进的空格数是可变的,但是同一个代码块的语句必须包含相同的缩进空格数。实例如下:
实例(Python 3.0+)
if True:
print ("True")
else:
print ("False")
多行语句
Python 通常是一行写完一条语句,但如果语句很长,我们可以使用反斜杠 \ 来实现多行语句,例如:
total = item_one + \
item_two + \
item_three
同一行显示多条语句
Python 可以在同一行中使用多条语句,语句之间使用分号 ; 分割,以下是一个简单的实例:
实例(Python 3.0+)
#!/usr/bin/python3
import sys; x = 'runoob'; sys.stdout.write(x + '\n')
多个语句构成代码组
缩进相同的一组语句构成一个代码块,我们称之代码组。
像if、while、def和class这样的复合语句,首行以关键字开始,以冒号( : )结束,该行之后的一行或多行代码构成代码组。
我们将首行及后面的代码组称为一个子句(clause)。
如下实例:
if expression :
suite
elif expression :
suite
else :
suite
在Python中,有三种主要的循环语句:for循环、while循环和do-while循环(在Python中没有原生的do-while循环,但可以使用while循环实现类似的功能)。下面是这些循环语句的示例:
for循环:
for循环用于遍历可迭代对象(如列表、元组、字符串等)中的元素。
示例:
fruits = ['apple', 'banana', 'cherry']
for fruit in fruits:
print(fruit)
# 输出:
# apple
# banana
# cherry
while循环:
while循环在条件为真时重复执行代码块,直到条件为假。
示例:
count = 0
while count < 5:
print(count)
count += 1
# 输出:
# 0
# 1
# 2
# 3
# 4
do-while循环(使用while循环实现):
do-while循环首先执行代码块,然后在条件为真时重复执行。
示例:
count = 0
while True:
print(count)
count += 1
if count >= 5:
break
# 输出:
# 0
# 1
# 2
# 3
# 4
Python中无switch语句
import 与 from...import
在 python 用 import 或者 from...import 来导入相应的模块。
将整个模块(somemodule)导入,格式为: import somemodule
从某个模块中导入某个函数,格式为: from somemodule import somefunction
从某个模块中导入多个函数,格式为: from somemodule import firstfunc, secondfunc, thirdfunc
将某个模块中的全部函数导入,格式为: from somemodule import *
导入 sys 模块
import sys
print('================Python import mode==========================')
print ('命令行参数为:')
for i in sys.argv:
print (i)
print ('\n python 路径为',sys.path)
导入 sys 模块的 argv,path 成员
from sys import argv,path # 导入特定的成员
print('================python from import===================================')
print('path:',path) # 因为已经导入path成员,所以此处引用时不需要加sys.path
Python3 基本数据类型
Python 中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建
多个变量赋值
Python允许你同时为多个变量赋值。例如:
a = b = c = 1
以上实例,创建一个整型对象,值为 1,从后向前赋值,三个变量被赋予相同的数值。
您也可以为多个对象指定多个变量。例如:
a, b, c = 1, 2, "runoob"
以上实例,两个整型对象 1 和 2 的分配给变量 a 和 b,字符串对象 "runoob" 分配给变量 c。
标准数据类型
Python3 中常见的数据类型有:
Number(数字)
String(字符串)
bool(布尔类型)
List(列表)
Tuple(元组)
Set(集合)
Dictionary(字典)
Python3 的六个标准数据类型中:
不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);
可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。
此外还有一些高级的数据类型,如: 字节数组类型(bytes)。
List(列表)
变量[头下标:尾下标]
索引值以 0 为开始值,-1 为从末尾的开始位置。
list = [ 'abcd', 786 , 2.23, 'runoob', 70.2 ]
tinylist = [123, 'runoob']
print (list) # 输出完整列表
print (list[0]) # 输出列表第一个元素
print (list[1:3]) # 从第二个开始输出到第三个元素
print (list[2:]) # 输出从第三个元素开始的所有元素
print (tinylist * 2) # 输出两次列表
print (list + tinylist) # 连接列表
注意:
1、List写在方括号之间,元素用逗号隔开。
2、和字符串一样,list可以被索引和切片。
3、List可以使用+操作符进行拼接。
4、List中的元素是可以改变的
Tuple(元组)
元组(tuple)与列表类似,不同之处在于元组的元素不能修改。元组写在小括号 () 里,元素之间用逗号隔开。
元组中的元素类型也可以不相同:
实例
#!/usr/bin/python3
tuple = ( 'abcd', 786 , 2.23, 'runoob', 70.2 )
tinytuple = (123, 'runoob')
print (tuple) # 输出完整元组
print (tuple[0]) # 输出元组的第一个元素
print (tuple[1:3]) # 输出从第二个元素开始到第三个元素
print (tuple[2:]) # 输出从第三个元素开始的所有元素
print (tinytuple * 2) # 输出两次元组
print (tuple + tinytuple) # 连接元组
Set(集合)
集合(set)是由一个或数个形态各异的大小整体组成的,构成集合的事物或对象称作元素或是成员。
基本功能是进行成员关系测试和删除重复元素。
可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
创建格式:
parame = {value01,value02,...}
或者
set(value)
实例
#!/usr/bin/python3
sites = {'Google', 'Taobao', 'Runoob', 'Facebook', 'Zhihu', 'Baidu'}
print(sites) # 输出集合,重复的元素被自动去掉
# 成员测试
if 'Runoob' in sites :
print('Runoob 在集合中')
else :
print('Runoob 不在集合中')
# set可以进行集合运算
a = set('abracadabra')
b = set('alacazam')
print(a)
print(a - b) # a 和 b 的差集
print(a | b) # a 和 b 的并集
print(a & b) # a 和 b 的交集
print(a ^ b) # a 和 b 中不同时存在的元素
以上实例输出结果:
{'Zhihu', 'Baidu', 'Taobao', 'Runoob', 'Google', 'Facebook'}
Runoob 在集合中
{'b', 'c', 'a', 'r', 'd'}
{'r', 'b', 'd'}
{'b', 'c', 'a', 'z', 'm', 'r', 'l', 'd'}
{'c', 'a'}
{'z', 'b', 'm', 'r', 'l', 'd'}
Dictionary(字典)
字典(dictionary)是Python中另一个非常有用的内置数据类型。
列表是有序的对象集合,字典是无序的对象集合。两者之间的区别在于:字典当中的元素是通过键来存取的,而不是通过偏移存取。
字典是一种映射类型,字典用 { } 标识,它是一个无序的 键(key) : 值(value) 的集合。
键(key)必须使用不可变类型。
在同一个字典中,键(key)必须是唯一的。
在Python中,你可以使用字典的各种方法来添加、编辑和删除元素。下面是一些常用的操作示例:
添加元素:
使用赋值操作将新的键值对添加到字典中。
示例:
复制
my_dict = {'name': 'Alice', 'age': 25}
my_dict['city'] = 'New York' # {'name': 'Alice', 'age': 25, 'city': 'New York'}
编辑元素:
通过键来访问字典中的元素,并对其进行赋值操作。
示例:
my_dict = {'name': 'Alice', 'age': 25}
my_dict['age'] = 26 # {'name': 'Alice', 'age': 26}
删除元素:
使用del语句删除指定的键值对。
使用pop()方法删除指定键的键值对,并返回该值。
示例:
my_dict = {'name': 'Alice', 'age': 25, 'city': 'New York'}
del my_dict['age'] # {'name': 'Alice', 'city': 'New York'}
age = my_dict.pop('age') # {'name': 'Alice', 'city': 'New York'}, age = 25
实例
#!/usr/bin/python3
dict = {}
dict['one'] = "1 - 菜鸟教程"
dict[2] = "2 - 菜鸟工具"
tinydict = {'name': 'runoob','code':1, 'site': 'www.runoob.com'}
print (dict['one']) # 输出键为 'one' 的值
print (dict[2]) # 输出键为 2 的值
print (tinydict) # 输出完整的字典
print (tinydict.keys()) # 输出所有键
print (tinydict.values()) # 输出所有值
以上实例输出结果:
1 - 菜鸟教程
2 - 菜鸟工具
{'name': 'runoob', 'code': 1, 'site': 'www.runoob.com'}
dict_keys(['name', 'code', 'site'])
dict_values(['runoob', 1, 'www.runoob.com'])
构造函数 dict() 可以直接从键值对序列中构建字典如下:
实例
>>> dict([('Runoob', 1), ('Google', 2), ('Taobao', 3)])
{'Runoob': 1, 'Google': 2, 'Taobao': 3}
>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}
>>> dict(Runoob=1, Google=2, Taobao=3)
{'Runoob': 1, 'Google': 2, 'Taobao': 3}
{x: x**2 for x in (2, 4, 6)} 该代码使用的是字典推导式,更多推导式内容可以参考:Python 推导式。
另外,字典类型也有一些内置的函数,例如 clear()、keys()、values() 等。
注意:
1、字典是一种映射类型,它的元素是键值对。
2、字典的关键字必须为不可变类型,且不能重复。
3、创建空字典使用 { }。
bytes 类型
在 Python3 中,bytes 类型表示的是不可变的二进制序列(byte sequence)。
与字符串类型不同的是,bytes 类型中的元素是整数值(0 到 255 之间的整数),而不是 Unicode 字符。
bytes 类型通常用于处理二进制数据,比如图像文件、音频文件、视频文件等等。在网络编程中,也经常使用 bytes 类型来传输二进制数据。
创建 bytes 对象的方式有多种,最常见的方式是使用 b 前缀:
此外,也可以使用 bytes() 函数将其他类型的对象转换为 bytes 类型。bytes() 函数的第一个参数是要转换的对象,第二个参数是编码方式,如果省略第二个参数,则默认使用 UTF-8 编码:
x = bytes("hello", encoding="utf-8")
与字符串类型类似,bytes 类型也支持许多操作和方法,如切片、拼接、查找、替换等等。同时,由于 bytes 类型是不可变的,因此在进行修改操作时需要创建一个新的 bytes 对象。例如:
实例
x = b"hello"
y = x[1:3] # 切片操作,得到 b"el"
z = x + b"world" # 拼接操作,得到 b"helloworld"
需要注意的是,bytes 类型中的元素是整数值,因此在进行比较操作时需要使用相应的整数值。例如:
实例
x = b"hello"
if x[0] == ord("h"):
print("The first element is 'h'")
其中 ord() 函数用于将字符转换为相应的整数值。
字符串转bytes
字符串转bytes, 是用 encode() 方法
data = str_data.encode(encoding="utf-8")
int 转 bytes
用int对象的to_bytes()方法
# int variable
num = 7
# int to bytes
num_bytes = num.to_bytes(2, byteorder='big')
# display result and type
print(num_bytes)
print(type(num_bytes))
第2个参数,表示双字节整数中高低字符顺序,big 表示正常顺序,即低字节在前,高字节在后 b'\x00\x07'
little 表示,高字节在前,低字节在后。上例中,将2个参数改为little, 则显示出的数字为b’\x07\x00’
bytes 转int , 使用 int.from_bytes()方法
>>> d=3324
>>> byte_data=d.to_bytes(5,"big")
>>> byte_data
b'\x00\x00\x00\x0c\xfc'
>>> int_data = int.from_bytes(byte_data,"big")
>>> int_data
3324
dict, tuple, list 转bytes
dict, list, tuple 转bytes, 通常使用pickle序列化, 或用 json序列化
bytes 变量内容的操作
基本上字符串支持的操作,bytes 字节串也都支持,只不过是二进制方式,可读性较差。 .
如在字符串中查找、替换字符等
>>> a=b"alibaba"
>>> a.count(b'a')
3
>>> a.find(b'a',3)
4
>>> chr(a[4])
'a'
>>> b=a.replace(b'a',b'x')
>>> b
b'xlibxbx'
Python数据类型转换
下几个内置的函数可以执行数据类型之间的转换。这些函数返回一个新的对象,表示转换的值。
函数 描述
int(x [,base])
将x转换为一个整数
float(x)
将x转换到一个浮点数
complex(real [,imag])
创建一个复数
str(x)
将对象 x 转换为字符串
repr(x)
将对象 x 转换为表达式字符串
eval(str)
用来计算在字符串中的有效Python表达式,并返回一个对象
tuple(s)
将序列 s 转换为一个元组
list(s)
将序列 s 转换为一个列表
set(s)
转换为可变集合
dict(d)
创建一个字典。d 必须是一个 (key, value)元组序列。
frozenset(s)
转换为不可变集合
chr(x)
将一个整数转换为一个字符
ord(x)
将一个字符转换为它的整数值
hex(x)
将一个整数转换为一个十六进制字符串
oct(x)
将一个整数转换为一个八进制字符串
Python算术运算符
以下假设变量 a=10,变量 b=21:
运算符 描述 实例
+ 加 - 两个对象相加 a + b 输出结果 31
- 减 - 得到负数或是一个数减去另一个数 a - b 输出结果 -11
* 乘 - 两个数相乘或是返回一个被重复若干次的字符串 a * b 输出结果 210
/ 除 - x 除以 y b / a 输出结果 2.1
% 取模 - 返回除法的余数 b % a 输出结果 1
** 幂 - 返回x的y次幂 a**b 为10的21次方
// 取整除 - 往小的方向取整数
>>> 9//2
4
>>> -9//2
-5
Python比较运算符
以下假设变量a为10,变量b为20:
运算符 描述 实例
== 等于 - 比较对象是否相等 (a == b) 返回 False。
!= 不等于 - 比较两个对象是否不相等 (a != b) 返回 True。
> 大于 - 返回x是否大于y (a > b) 返回 False。
< 小于 - 返回x是否小于y。所有比较运算符返回1表示真,返回0表示假。这分别与特殊的变量True和False等价。注意,这些变量名的大写。 (a < b) 返回 True。
>= 大于等于 - 返回x是否大于等于y。 (a >= b) 返回 False。
<= 小于等于 - 返回x是否小于等于y。 (a <= b) 返回 True。
Python赋值运算符
以下假设变量a为10,变量b为20:
运算符 描述 实例
= 简单的赋值运算符 c = a + b 将 a + b 的运算结果赋值为 c
+= 加法赋值运算符 c += a 等效于 c = c + a
-= 减法赋值运算符 c -= a 等效于 c = c - a
*= 乘法赋值运算符 c *= a 等效于 c = c * a
/= 除法赋值运算符 c /= a 等效于 c = c / a
%= 取模赋值运算符 c %= a 等效于 c = c % a
**= 幂赋值运算符 c **= a 等效于 c = c ** a
//= 取整除赋值运算符 c //= a 等效于 c = c // a
:= 海象运算符,可在表达式内部为变量赋值。Python3.8 版本新增运算符。
在这个示例中,赋值表达式可以避免调用 len() 两次:
if (n := len(a)) > 10:
print(f"List is too long ({n} elements, expected <= 10)")
Python位运算符
& 按位与运算符:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0 (a & b) 输出结果 12 ,二进制解释: 0000 1100
| 按位或运算符:只要对应的二个二进位有一个为1时,结果位就为1。 (a | b) 输出结果 61 ,二进制解释: 0011 1101
^ 按位异或运算符:当两对应的二进位相异时,结果为1 (a ^ b) 输出结果 49 ,二进制解释: 0011 0001
~ 按位取反运算符:对数据的每个二进制位取反,即把1变为0,把0变为1。~x 类似于 -x-1 (~a ) 输出结果 -61 ,二进制解释: 1100 0011, 在一个有符号二进制数的补码形式。
<< 左移动运算符:运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0。 a << 2 输出结果 240 ,二进制解释: 1111 0000
>> 右移动运算符:把">>"左边的运算数的各二进位全部右移若干位,">>"右边的数指定移动的位数
Python逻辑运算符
Python语言支持逻辑运算符,以下假设变量 a 为 10, b为 20:
运算符 逻辑表达式 描述 实例
and x and y 布尔"与" - 如果 x 为 False,x and y 返回 x 的值,否则返回 y 的计算值。 (a and b) 返回 20。
or x or y 布尔"或" - 如果 x 是 True,它返回 x 的值,否则它返回 y 的计算值。 (a or b) 返回 10。
not not x 布尔"非" - 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。 not(a and b) 返回 False
以上实例输出结果:
实例(Python 3.0+)
#!/usr/bin/python3
a = 10
b = 20
if ( a and b ):
print ("1 - 变量 a 和 b 都为 true")
else:
print ("1 - 变量 a 和 b 有一个不为 true")
if ( a or b ):
print ("2 - 变量 a 和 b 都为 true,或其中一个变量为 true")
else:
print ("2 - 变量 a 和 b 都不为 true")
# 修改变量 a 的值
a = 0
if ( a and b ):
print ("3 - 变量 a 和 b 都为 true")
else:
print ("3 - 变量 a 和 b 有一个不为 true")
if ( a or b ):
print ("4 - 变量 a 和 b 都为 true,或其中一个变量为 true")
else:
print ("4 - 变量 a 和 b 都不为 true")
if not( a and b ):
print ("5 - 变量 a 和 b 都为 false,或其中一个变量为 false")
else:
print ("5 - 变量 a 和 b 都为 true")
Python成员运算符
除了以上的一些运算符之外,Python还支持成员运算符,测试实例中包含了一系列的成员,包括字符串,列表或元组。
运算符 描述 实例
in 如果在指定的序列中找到值返回 True,否则返回 False。 x 在 y 序列中 , 如果 x 在 y 序列中返回 True。
not in 如果在指定的序列中没有找到值返回 True,否则返回 False。 x 不在 y 序列中 , 如果 x 不在 y 序列中返回 True。
以下实例演示了Python所有成员运算符的操作:
实例(Python 3.0+)
#!/usr/bin/python3
a = 10
b = 20
list = [1, 2, 3, 4, 5 ]
if ( a in list ):
print ("1 - 变量 a 在给定的列表中 list 中")
else:
print ("1 - 变量 a 不在给定的列表中 list 中")
if ( b not in list ):
print ("2 - 变量 b 不在给定的列表中 list 中")
else:
print ("2 - 变量 b 在给定的列表中 list 中")
# 修改变量 a 的值
a = 2
if ( a in list ):
print ("3 - 变量 a 在给定的列表中 list 中")
else:
print ("3 - 变量 a 不在给定的列表中 list 中")
以上实例输出结果:
1 - 变量 a 不在给定的列表中 list 中
2 - 变量 b 不在给定的列表中 list 中
3 - 变量 a 在给定的列表中 list 中
Python身份运算符
身份运算符用于比较两个对象的存储单元
运算符 描述 实例
is is 是判断两个标识符是不是引用自一个对象 x is y, 类似 id(x) == id(y) , 如果引用的是同一个对象则返回 True,否则返回 False
is not is not 是判断两个标识符是不是引用自不同对象 x is not y , 类似 id(x) != id(y)。如果引用的不是同一个对象则返回结果 True,否则返回 False。
注: id() 函数用于获取对象内存地址。
以下实例演示了Python所有身份运算符的操作:
实例(Python 3.0+)
#!/usr/bin/python3
a = 20
b = 20
if ( a is b ):
print ("1 - a 和 b 有相同的标识")
else:
print ("1 - a 和 b 没有相同的标识")
if ( id(a) == id(b) ):
print ("2 - a 和 b 有相同的标识")
else:
print ("2 - a 和 b 没有相同的标识")
# 修改变量 b 的值
b = 30
if ( a is b ):
print ("3 - a 和 b 有相同的标识")
else:
print ("3 - a 和 b 没有相同的标识")
if ( a is not b ):
print ("4 - a 和 b 没有相同的标识")
else:
print ("4 - a 和 b 有相同的标识")
以上实例输出结果:
1 - a 和 b 有相同的标识
2 - a 和 b 有相同的标识
3 - a 和 b 没有相同的标识
4 - a 和 b 没有相同的标识
Python3 列表
访问列表中的值
与字符串的索引一样,列表索引从 0 开始,第二个索引是 1,依此类推。
实例
#!/usr/bin/python3
list = ['red', 'green', 'blue', 'yellow', 'white', 'black']
print( list[0] )
print( list[1] )
print( list[2] )
以上实例输出结果:
red
green
blue
在Python中,你可以使用列表的各种方法来添加、删除和编辑元素。下面是一些常用的操作示例:
添加元素:
使用append()方法在列表末尾添加一个元素。
使用insert()方法在指定位置插入一个元素。
示例:
my_list = [1, 2, 3]
my_list.append(4) # [1, 2, 3, 4]
my_list.insert(1, 5) # [1, 5, 2, 3, 4]
删除元素:
使用remove()方法删除列表中的特定元素。
使用del语句删除指定位置的元素。
示例:
my_list = [1, 2, 3, 4]
my_list.remove(3) # [1, 2, 4]
del my_list[0] # [2, 4]
编辑元素:
直接通过索引对列表中的元素进行赋值操作。
示例:
my_list = [1, 2, 3]
my_list[1] = 5 # [1, 5, 3]
索引也可以从尾部开始,最后一个元素的索引为 -1,往前一位为 -2,以此类推
实例
#!/usr/bin/python3
list = ['red', 'green', 'blue', 'yellow', 'white', 'black']
print( list[-1] )
print( list[-2] )
print( list[-3] )
以上实例输出结果:
black
white
yellow
使用下标索引来访问列表中的值,同样你也可以使用方括号 [] 的形式截取字符,如下所示:
实例
#!/usr/bin/python3
nums = [10, 20, 30, 40, 50, 60, 70, 80, 90]
print(nums[0:4])
以上实例输出结果:
[10, 20, 30, 40]
使用负数索引值截取:
实例
#!/usr/bin/python3
list = ['Google', 'Runoob', "Zhihu", "Taobao", "Wiki"]
# 读取第二位
print ("list[1]: ", list[1])
# 从第二位开始(包含)截取到倒数第二位(不包含)
print ("list[1:-2]: ", list[1:-2])
以上实例输出结果:
list[1]: Runoob
list[1:-2]: ['Runoob', 'Zhihu']
删除列表元素
可以使用 del 语句来删除列表的的元素,如下实例:
实例(Python 3.0+)
#!/usr/bin/python3
list = ['Google', 'Runoob', 1997, 2000]
print ("原始列表 : ", list)
del list[2]
print ("删除第三个元素 : ", list)
以上实例输出结果:
原始列表 : ['Google', 'Runoob', 1997, 2000]
删除第三个元素 : ['Google', 'Runoob', 2000]
Python列表脚本操作符
列表对 + 和 * 的操作符与字符串相似。+ 号用于组合列表,* 号用于重复列表。
如下所示:
Python 表达式 结果 描述
len([1, 2, 3]) 3 长度
[1, 2, 3] + [4, 5, 6] [1, 2, 3, 4, 5, 6] 组合
['Hi!'] * 4 ['Hi!', 'Hi!', 'Hi!', 'Hi!'] 重复
3 in [1, 2, 3] True 元素是否存在于列表中
for x in [1, 2, 3]: print(x, end=" ") 1 2 3 迭代
嵌套列表
使用嵌套列表即在列表里创建其它列表,例如:
>>>a = ['a', 'b', 'c']
>>> n = [1, 2, 3]
>>> x = [a, n]
>>> x
[['a', 'b', 'c'], [1, 2, 3]]
>>> x[0]
['a', 'b', 'c']
>>> x[0][1]
'b'
列表比较
列表比较需要引入 operator 模块的 eq 方法(详见:Python operator 模块):
实例
# 导入 operator 模块
import operator
a = [1, 2]
b = [2, 3]
c = [2, 3]
print("operator.eq(a,b): ", operator.eq(a,b))
print("operator.eq(c,b): ", operator.eq(c,b))
以上代码输出结果为:
operator.eq(a,b): False
operator.eq(c,b): True
Python列表函数&方法
Python包含以下函数:
序号 函数
1 len(list)
列表元素个数
2 max(list)
返回列表元素最大值
3 min(list)
返回列表元素最小值
4 list(seq)
将元组转换为列表
Python包含以下方法:
序号 方法
1 list.append(obj)
在列表末尾添加新的对象
2 list.count(obj)
统计某个元素在列表中出现的次数
3 list.extend(seq)
在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)
4 list.index(obj)
从列表中找出某个值第一个匹配项的索引位置
5 list.insert(index, obj)
将对象插入列表
6 list.pop([index=-1])
移除列表中的一个元素(默认最后一个元素),并且返回该元素的值
7 list.remove(obj)
移除列表中某个值的第一个匹配项
8 list.reverse()
反向列表中元素
9 list.sort( key=None, reverse=False)
对原列表进行排序
10 list.clear()
清空列表
11 list.copy()
复制列表
Python3 字典
访问字典里的值
把相应的键放入到方括号中,如下实例:
实例
#!/usr/bin/python3
tinydict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
print ("tinydict['Name']: ", tinydict['Name'])
print ("tinydict['Age']: ", tinydict['Age'])
以上实例输出结果:
tinydict['Name']: Runoob
tinydict['Age']: 7
修改字典
向字典添加新内容的方法是增加新的键/值对,修改或删除已有键/值对如下实例:
实例
#!/usr/bin/python3
tinydict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
tinydict['Age'] = 8 # 更新 Age
tinydict['School'] = "菜鸟教程" # 添加信息
print ("tinydict['Age']: ", tinydict['Age'])
print ("tinydict['School']: ", tinydict['School'])
以上实例输出结果:
tinydict['Age']: 8
tinydict['School']: 菜鸟教程
删除字典元素
能删单一的元素也能清空字典,清空只需一项操作。
显式删除一个字典用del命令,如下实例:
实例
#!/usr/bin/python3
tinydict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
del tinydict['Name'] # 删除键 'Name'
tinydict.clear() # 清空字典
del tinydict # 删除字典
print ("tinydict['Age']: ", tinydict['Age'])
print ("tinydict['School']: ", tinydict['School'])
但这会引发一个异常,因为用执行 del 操作后字典不再存在:
Traceback (most recent call last):
File "/runoob-test/test.py", line 9, in <module>
print ("tinydict['Age']: ", tinydict['Age'])
NameError: name 'tinydict' is not defined
字典内置函数&方法
Python字典包含了以下内置函数:
序号 函数及描述 实例
1 len(dict)
计算字典元素个数,即键的总数。
>>> tinydict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
>>> len(tinydict)
3
2 str(dict)
输出字典,可以打印的字符串表示。
>>> tinydict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
>>> str(tinydict)
"{'Name': 'Runoob', 'Class': 'First', 'Age': 7}"
3 type(variable)
返回输入的变量类型,如果变量是字典就返回字典类型。
>>> tinydict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
>>> type(tinydict)
<class 'dict'>
Python字典包含了以下内置方法:
序号 函数及描述
1 dict.clear()
删除字典内所有元素
2 dict.copy()
返回一个字典的浅复制
3 dict.fromkeys()
创建一个新字典,以序列seq中元素做字典的键,val为字典所有键对应的初始值
4 dict.get(key, default=None)
返回指定键的值,如果键不在字典中返回 default 设置的默认值
5 key in dict
如果键在字典dict里返回true,否则返回false
6 dict.items()
以列表返回一个视图对象
7 dict.keys()
返回一个视图对象
8 dict.setdefault(key, default=None)
和get()类似, 但如果键不存在于字典中,将会添加键并将值设为default
9 dict.update(dict2)
把字典dict2的键/值对更新到dict里
10 dict.values()
返回一个视图对象
11 pop(key[,default])
删除字典 key(键)所对应的值,返回被删除的值。
12 popitem()
返回并删除字典中的最后一对键和值。
Python3 集合
集合(set)是一个无序的不重复元素序列
可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
创建格式:
parame = {value01,value02,...}
或者
set(value)
集合的基本操作
1、添加元素
语法格式如下:
s.add( x )
将元素 x 添加到集合 s 中,如果元素已存在,则不进行任何操作
2、移除元素
语法格式如下:
s.remove( x )
将元素 x 从集合 s 中移除,如果元素不存在,则会发生错误
3、计算集合元素个数
语法格式如下:
len(s)
计算集合 s 元素个数。
4、清空集合
语法格式如下:
s.clear()
5、判断元素是否在集合中存在
语法格式如下:
x in s
判断元素 x 是否在集合 s 中,存在返回 True,不存在返回 False。
集合内置方法完整列表
方法 描述
add() 为集合添加元素
clear() 移除集合中的所有元素
copy() 拷贝一个集合
difference() 返回多个集合的差集
difference_update() 移除集合中的元素,该元素在指定的集合也存在。
discard() 删除集合中指定的元素
intersection() 返回集合的交集
intersection_update() 返回集合的交集。
isdisjoint() 判断两个集合是否包含相同的元素,如果没有返回 True,否则返回 False。
issubset() 判断指定集合是否为该方法参数集合的子集。
issuperset() 判断该方法的参数集合是否为指定集合的子集
pop() 随机移除元素
remove() 移除指定元素
symmetric_difference() 返回两个集合中不重复的元素集合。
symmetric_difference_update() 移除当前集合中在另外一个指定集合相同的元素,并将另外一个指定集合中不同的元素插入到当前集合中。
union() 返回两个集合的并集
update() 给集合添加元素
Python3 条件控制
if 语句
Python中if语句的一般形式如下所示:
if condition_1:
statement_block_1
elif condition_2:
statement_block_2
else:
statement_block_3
a = 50
if (a< 100 and a > 10 or (a >20 and a<100):
print "a is true"
else:
print 'a is false'
match...case
Python 3.10 增加了 match...case 的条件判断,不需要再使用一连串的 if-else 来判断了。
match 后的对象会依次与 case 后的内容进行匹配,如果匹配成功,则执行匹配到的表达式,否则直接跳过,_ 可以匹配一切。
语法格式如下:
match subject:
case <pattern_1>:
<action_1>
case <pattern_2>:
<action_2>
case <pattern_3>:
<action_3>
case _:
<action_wildcard>
Python3 循环语句
while 循环
Python 中 while 语句的一般形式:
while 判断条件(condition):
执行语句(statements)……
#!/usr/bin/env python3
n = 100
sum = 0
counter = 1
while counter <= n:
sum = sum + counter
counter += 1
print("1 到 %d 之和为: %d" % (n,sum))
执行结果如下:
1 到 100 之和为: 5050
无限循环
我们可以通过设置条件表达式永远不为 false 来实现无限循环,实例如下:
实例
#!/usr/bin/python3
var = 1
while var == 1 : # 表达式永远为 true
num = int(input("输入一个数字 :"))
print ("你输入的数字是: ", num)
while 循环使用 else 语句
如果 while 后面的条件语句为 false 时,则执行 else 的语句块。
语法格式如下:
while <expr>:
<statement(s)>
else:
<additional_statement(s)>
expr 条件语句为 true 则执行 statement(s) 语句块,如果为 false,则执行 additional_statement(s)。
循环输出数字,并判断大小:
实例
#!/usr/bin/python3
count = 0
while count < 5:
print (count, " 小于 5")
count = count + 1
else:
print (count, " 大于或等于 5")
执行以上脚本,输出结果如下:
0 小于 5
1 小于 5
2 小于 5
3 小于 5
4 小于 5
5 大于或等于 5
print ("Good bye!")
for 语句
Python for 循环可以遍历任何可迭代对象,如一个列表或者一个字符串。
for循环的一般格式如下:
for <variable> in <sequence>:
<statements>
else:
<statements>
Python for 循环实例:
实例
#!/usr/bin/python3
sites = ["Baidu", "Google","Runoob","Taobao"]
for site in sites:
print(site)
以上代码执行输出结果为:
Baidu
Runoob
Taobao
for...else
在 Python 中,for...else 语句用于在循环结束后执行一段代码。
语法格式如下:
for item in iterable:
# 循环主体
else:
# 循环结束后执行的代码
当循环执行完毕(即遍历完 iterable 中的所有元素)后,会执行 else 子句中的代码,如果在循环过程中遇到了 break 语句,则会中断循环,此时不会执行 else 子句。
实例
for x in range(6):
print(x)
else:
print("Finally finished!")
执行脚本后,输出结果为:
0
1
2
3
4
5
Finally finished!
以下 for 实例中使用了 break 语句,break 语句用于跳出当前循环体,不会执行 else 子句:
实例
#!/usr/bin/python3
sites = ["Baidu", "Google","Runoob","Taobao"]
for site in sites:
if site == "Runoob":
print("菜鸟教程!")
break
print("循环数据 " + site)
else:
print("没有循环数据!")
print("完成循环!")
执行脚本后,在循环到 "Runoob"时会跳出循环体:
循环数据 Baidu
循环数据 Google
菜鸟教程!
完成循环!
range() 函数
如果你需要遍历数字序列,可以使用内置 range() 函数。它会生成数列,例如:
实例
>>>for i in range(5):
... print(i)
...
0
1
2
3
4
break 和 continue 语句及循环中的 else 子句
break 语句可以跳出 for 和 while 的循环体。如果你从 for 或 while 循环中终止,任何对应的循环 else 块将不执行。
continue 语句被用来告诉 Python 跳过当前循环块中的剩余语句,然后继续进行下一轮循环。
pass 语句
Python pass是空语句,是为了保持程序结构的完整性。
pass 不做任何事情,一般用做占位语句
Python3 函数
定义一个函数
你可以定义一个由自己想要功能的函数,以下是简单的规则:
函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
函数内容以冒号 : 起始,并且缩进。
return [表达式] 结束函数,选择性地返回一个值给调用方,不带表达式的 return 相当于返回 None。
参数
以下是调用函数时可使用的正式参数类型:
必需参数
关键字参数
默认参数
不定长参数
以下实例中演示了函数参数的使用不需要使用指定顺序:
实例(Python 3.0+)
#!/usr/bin/python3
#可写函数说明
def printinfo( name, age ):
"打印任何传入的字符串"
print ("名字: ", name)
print ("年龄: ", age)
return
#调用printinfo函数
printinfo( age=50, name="runoob" )
默认参数
调用函数时,如果没有传递参数,则会使用默认参数。以下实例中如果没有传入 age 参数,则使用默认值:
实例(Python 3.0+)
#!/usr/bin/python3
#可写函数说明
def printinfo( name, age = 35 ):
"打印任何传入的字符串"
print ("名字: ", name)
print ("年龄: ", age)
return
#调用printinfo函数
printinfo( age=50, name="runoob" )
print ("------------------------")
printinfo( name="runoob" )
不定长参数
如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量。如下实例:
实例(Python 3.0+)
#!/usr/bin/python3
# 可写函数说明
def printinfo( arg1, *vartuple ):
"打印任何传入的参数"
print ("输出: ")
print (arg1)
for var in vartuple:
print (var)
return
# 调用printinfo 函数
printinfo( 10 )
printinfo( 70, 60, 50 )
加了两个星号 ** 的参数会以字典的形式导入。
实例(Python 3.0+)
#!/usr/bin/python3
# 可写函数说明
def printinfo( arg1, **vardict ):
"打印任何传入的参数"
print ("输出: ")
print (arg1)
print (vardict)
# 调用printinfo 函数
printinfo(1, a=2,b=3)
Python3 模块
标准库的方法。
下面是一个使用 python 标准库中模块的例子。
实例(Python 3.0+)
#!/usr/bin/python3
# 文件名: using_sys.py
import sys
print('命令行参数如下:')
for i in sys.argv:
print(i)
print('\n\nPython 路径为:', sys.path, '\n')
执行结果如下所示:
$ python using_sys.py 参数1 参数2
命令行参数如下:
using_sys.py
参数1
参数2
Python 路径为: ['/root', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/usr/local/lib/python3.4/dist-packages', '/usr/lib/python3/dist-packages']
1、import sys 引入 python 标准库中的 sys.py 模块;这是引入某一模块的方法。
2、sys.argv 是一个包含命令行参数的列表。
3、sys.path 包含了一个 Python 解释器自动查找所需模块的路径的列表。
import 语句
想使用 Python 源文件,只需在另一个源文件里执行 import 语句,语法如下:
import module1[, module2[,... moduleN]
当解释器遇到 import 语句,如果模块在当前的搜索路径就会被导入。
搜索路径是一个解释器会先进行搜索的所有目录的列表。如想要导入模块 support,需要把命令放在脚本的顶端:
support.py 文件代码
#!/usr/bin/python3
# Filename: support.py
def print_func( par ):
print ("Hello : ", par)
return
test.py 引入 support 模块:
test.py 文件代码
#!/usr/bin/python3
# Filename: test.py
# 导入模块
import support
# 现在可以调用模块里包含的函数了
support.print_func("Runoob")
以上实例输出结果:
$ python3 test.py
Hello : Runoob
from … import 语句
Python 的 from 语句让你从模块中导入一个指定的部分到当前命名空间中,语法如下:
from modname import name1[, name2[, ... nameN]]
例如,要导入模块 fibo 的 fib 函数,使用如下语句:
>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
这个声明不会把整个fibo模块导入到当前的命名空间中,它只会将fibo里的fib函数引入进来。
from … import * 语句
把一个模块的所有内容全都导入到当前的命名空间也是可行的,只需使用如下声明:
from modname import *
这提供了一个简单的方法来导入一个模块中的所有项目。然而这种声明不该被过多地使用。
Python3 面向对象
面向对象技术简介
类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
方法:类中定义的函数。
类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
局部变量:定义在方法中的变量,只作用于当前实例的类。
实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
实例化:创建一个类的实例,类的具体对象。
对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
Python的类函数区分私有公共吗
Python中的类函数可以区分私有和公共。在Python中,使用双下划线(__)作为类函数或属性的前缀表示私有,外部调用时无法直接访问,需要通过类内部的函数实现访问;不使用双下划线作为前缀的函数或属性表示公共,可以在类的任何地方被访问。示例代码如下:
class MyClass:
def __init__(self):
self.__private_var = 1
self.public_var = 2
def __private_func(self):
print("This is a private function")
def public_func(self):
print("This is a public function")
self.__private_func()
在上面的代码中,__init__函数中定义了一个私有变量__private_var和一个公共变量public_var。同时,类中还定义了一个私有函数__private_func和一个公共函数public_func。从外部调用时,私有变量和函数无法直接访问,但公共变量和函数可以通过类的实例进行访问。
# 创建实例
mc = MyClass()
# 访问公共变量和函数
print(mc.public_var) # 输出:2
mc.public_func() # 输出:This is a public function
# This is a private function
# 无法直接访问私有变量和函数
print(mc.__private_var) # 报错:'MyClass' object has no attribute '__private_var'
mc.__private_func() # 报错:'MyClass' object has no attribute '__private_func'
类定义
语法格式如下:
class ClassName:
<statement-1>
.
.
.
<statement-N>
类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名访问其属性。
类对象
类对象支持两种操作:属性引用和实例化。
属性引用使用和 Python 中所有的属性引用一样的标准语法:obj.name。
类对象创建后,类命名空间中所有的命名都是有效属性名。所以如果类定义是这样:
实例(Python 3.0+)
#!/usr/bin/python3
class MyClass:
"""一个简单的类实例"""
i = 12345
def f(self):
return 'hello world'
# 实例化类
x = MyClass()
# 访问类的属性和方法
print("MyClass 类的属性 i 为:", x.i)
print("MyClass 类的方法 f 输出为:", x.f())
self代表类的实例,而非类
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。
class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt()
self 不是 python 关键字,我们把他换成 runoob 也是可以正常执行的:
class Test:
def prt(runoob):
print(runoob)
print(runoob.__class__)
t = Test()
t.prt()
类的方法
在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self, 且为第一个参数,self 代表的是类的实例。
实例(Python 3.0+)
#!/usr/bin/python3
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
# 实例化类
p = people('runoob',10,30)
p.speak()
执行以上程序输出结果为:
runoob 说: 我 10 岁。
继承
Python 同样支持类的继承,如果一种语言不支持继承,类就没有什么意义。派生类的定义如下所示:
class DerivedClassName(BaseClassName):
<statement-1>
.
.
.
<statement-N>
子类(派生类 DerivedClassName)会继承父类(基类 BaseClassName)的属性和方法。
BaseClassName(实例中的基类名)必须与派生类定义在一个作用域内。除了类,还可以用表达式,基类定义在另一个模块中时这一点非常有用:
class DerivedClassName(modname.BaseClassName):
实例(Python 3.0+)
#!/usr/bin/python3
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
#单继承示例
class student(people):
grade = ''
def __init__(self,n,a,w,g):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
#覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
s = student('ken',10,60,3)
s.speak()
执行以上程序输出结果为:
ken 说: 我 10 岁了,我在读 3 年级
多继承
Python同样有限的支持多继承形式。多继承的类定义形如下例:
class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>
需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 即方法在子类中未找到时,从左到右查找父类中是否包含方法。
实例(Python 3.0+)
#!/usr/bin/python3
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
#单继承示例
class student(people):
grade = ''
def __init__(self,n,a,w,g):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
#覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
#另一个类,多重继承之前的准备
class speaker():
topic = ''
name = ''
def __init__(self,n,t):
self.name = n
self.topic = t
def speak(self):
print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))
#多重继承
class sample(speaker,student):
a =''
def __init__(self,n,a,w,g,t):
student.__init__(self,n,a,w,g)
speaker.__init__(self,n,t)
test = sample("Tim",25,80,4,"Python")
test.speak() #方法名同,默认调用的是在括号中参数位置排前父类的方法
执行以上程序输出结果为:
我叫 Tim,我是一个演说家,我演讲的主题是 Python
方法重写
如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法,实例如下:
实例(Python 3.0+)
#!/usr/bin/python3
class Parent: # 定义父类
def myMethod(self):
print ('调用父类方法')
class Child(Parent): # 定义子类
def myMethod(self):
print ('调用子类方法')
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
super(Child,c).myMethod() #用子类对象调用父类已被覆盖的方法
super() 函数是用于调用父类(超类)的一个方法。
执行以上程序输出结果为:
调用子类方法
调用父类方法
Python3标准库
Python 标准库非常庞大,所提供的组件涉及范围十分广泛,使用标准库我们可以让您轻松地完成各种任务。
以下是一些 Python3 标准库中的模块:
os 模块:os 模块提供了许多与操作系统交互的函数,例如创建、移动和删除文件和目录,以及访问环境变量等。
sys 模块:sys 模块提供了与 Python 解释器和系统相关的功能,例如解释器的版本和路径,以及与 stdin、stdout 和 stderr 相关的信息。
time 模块:time 模块提供了处理时间的函数,例如获取当前时间、格式化日期和时间、计时等。
datetime 模块:datetime 模块提供了更高级的日期和时间处理函数,例如处理时区、计算时间差、计算日期差等。
random 模块:random 模块提供了生成随机数的函数,例如生成随机整数、浮点数、序列等。
math 模块:math 模块提供了数学函数,例如三角函数、对数函数、指数函数、常数等。
re 模块:re 模块提供了正则表达式处理函数,可以用于文本搜索、替换、分割等。
json 模块:json 模块提供了 JSON 编码和解码函数,可以将 Python 对象转换为 JSON 格式,并从 JSON 格式中解析出 Python 对象。
urllib 模块:urllib 模块提供了访问网页和处理 URL 的功能,包括下载文件、发送 POST 请求、处理 cookies 等。
Python开启新线程的代码
以下是Python开启新线程的代码示例:
```python
import threading
# 定义一个函数作为线程的执行内容
def thread_function():
print("This is a new thread.")
# 创建一个新的线程并启动它
new_thread = threading.Thread(target=thread_function)
new_thread.start()
print("Main thread continues here.")
```
在这个例子中,我们首先定义了一个函数`thread_function()`,这个函数表示线程的执行内容。然后,使用`threading.Thread()`创建了一个新的线程对象`new_thread`,传入`target=thread_function`参数表示该线程的执行内容为`thread_function()`函数。接着,使用`new_thread.start()`启动新线程。最后,在主线程中输出一条信息表示主线程继续执行。
需要注意的是,开启新线程会消耗一定的系统资源,如果线程过多,可能会导致系统负荷过重。因此,需要谨慎使用多线程技术
import threading
import time
exitFlag = 0
class myThread (threading.Thread):
def __init__(self, threadID, name, delay):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.delay = delay
def run(self):
print ("开始线程:" + self.name)
print_time(self.name, self.delay, 5)
print ("退出线程:" + self.name)
def print_time(threadName, delay, counter):
while counter:
if exitFlag:
threadName.exit()
time.sleep(delay)
print ("%s: %s" % (threadName, time.ctime(time.time())))
counter -= 1
# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# 开启新线程
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print ("退出主线程")
Python3 通过两个标准库 _thread 和 threading 提供对线程的支持。
_thread 提供了低级别的、原始的线程以及一个简单的锁,它相比于 threading 模块的功能还是比较有限的。
threading 模块除了包含 _thread 模块中的所有方法外,还提供的其他方法:
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:
run(): 用以表示线程活动的方法。
start():启动线程活动。
join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名。
Python线程同步代码例子
下面是一个简单的Python线程同步代码例子:
```
import threading
class Counter:
def __init__(self):
self.lock = threading.Lock()
self.count = 0
def increment(self):
with self.lock:
self.count += 1
def worker(counter):
for i in range(100):
counter.increment()
# 创建一个计数器对象
counter = Counter()
# 创建10个线程
threads = []
for i in range(10):
t = threading.Thread(target=worker, args=(counter,))
threads.append(t)
t.start()
# 等待所有线程结束
for t in threads:
t.join()
# 输出计数器的值
print(counter.count)
```
在这个例子中,我们创建了一个计数器对象,它有一个 `increment` 方法可以对计数器进行加1的操作,同时使用了一个 `Lock` 对象来保证线程安全。然后我们创建了10个线程,每个线程都会对计数器进行100次加1操作。最后输出计数器的值,应该是1000。。
Python线程的同步机制
Python线程的同步机制包括:
1. Lock(锁):只允许一个线程访问共享资源,其他线程需要等待锁被释放后才能访问。
2. RLock(可重入锁):可以被同一个线程多次获得,并且不会被其它线程所获取的锁。
3. Semaphore(信号量):用于控制同时访问共享资源的线程数量。
4. Event(事件):用于线程之间的通信,一个线程可以设置事件,其他线程可以等待事件。
5. Condition(条件变量):用于线程之间的协调,一个或多个线程等待某个条件变量的可用性,并在可用时修改条件变量以通知其他线程。
6. Barrier(屏障):用于同步多个线程,要求在所有线程都到达屏障之前,不能继续执行。
7. Queue(队列):用于线程之间的通信,可以实现生产者-消费者模型。
以下是 Python Lock 的实例代码,包括锁定、释放锁定和使用锁定:
```python
import threading
lock = threading.Lock()
# 锁定
lock.acquire()
# 临界区代码
# ...
# 释放锁定
lock.release()
# 使用 with 语句自动锁定和释放
with lock:
# 临界区代码
# ...
# 在函数中使用锁定
def some_func():
with lock:
# 临界区代码
# ...
下面是一个简单的 Python RLock 示例代码:
```python
import threading
class SharedResource:
def __init__(self):
self._lock = threading.RLock()
self.counter = 0
def increment(self):
with self._lock:
self.counter += 1
def decrement(self):
with self._lock:
self.counter -= 1
if __name__ == "__main__":
# 创建共享资源对象
sr = SharedResource()
# 创建增加计数器线程
t1 = threading.Thread(target=sr.increment)
t2 = threading.Thread(target=sr.increment)
t3 = threading.Thread(target=sr.increment)
# 创建减少计数器线程
t4 = threading.Thread(target=sr.decrement)
t5 = threading.Thread(target=sr.decrement)
# 启动线程
t1.start()
t2.start()
t3.start()
t4.start()
t5.start()
# 等待线程结束
t1.join()
t2.join()
t3.join()
t4.join()
t5.join()
# 打印计数器值
print("Counter value is %d" % sr.counter)
```
这个例子中,我们创建了一个名为 `SharedResource` 的对象,其中包含了一个计数器属性和一个 RLock 对象。我们使用 `with` 语句来确保在修改计数器属性时只有一个线程可以访问该属性。我们还创建了几个线程来增加和减少计数器的值,并使用 `join()` 方法等待所有线程结束。最后,我们打印计数器属性的值。
```
以下是一个使用Semaphore的Python示例代码:
```python
import threading
# 创建Semaphore对象,初始值为5,表示最多只能有5个线程同时执行
semaphore = threading.Semaphore(5)
def worker(num):
# 获取锁定(如果锁定的计数器值<=0,则阻塞等待)
semaphore.acquire()
print("Worker {} is working...".format(num))
# 模拟工作
for i in range(5):
print("Worker {} is processing...".format(num))
# 释放锁定
semaphore.release()
# 创建10个线程
threads = []
for i in range(10):
t = threading.Thread(target=worker, args=(i,))
threads.append(t)
t.start()
# 等待所有线程完成
for t in threads:
t.join()
```
这个示例代码创建了一个Semaphore对象,并将其初始化为5。然后创建了10个线程,并执行worker函数。在每个线程中,使用acquire方法获取Semaphore锁定。如果Semaphore的计数器值<=0,则该线程被阻塞等待锁定。当线程获取锁定后,执行一些工作,并使用release方法释放锁定。由于Semaphore的初始值为5,因此最多只能有5个线程同时运行。当有一个线程释放了锁定时,将允许其他阻塞的线程获取锁定并继续执行。
以下是一个使用 Python 实现 Event 的示例代码:
```python
from threading import Thread, Event
import time
# 线程1
def worker1(event, num):
print("Worker 1 is starting...")
time.sleep(num) # 模拟任务执行时间
event.set() # 任务完成,设置 event
# 线程2
def worker2(event):
print("Worker 2 is starting...")
event.wait() # 等待 event 被设置
print("Worker 2 is done.")
if __name__ == "__main__":
event = Event() # 实例化 event
thread1 = Thread(target=worker1, args=(event, 3)) # 传入 event 和任务执行时间
thread2 = Thread(target=worker2, args=(event,))
thread1.start() # 启动线程1
thread2.start() # 启动线程2
thread1.join() # 等待线程1执行完毕
thread2.join() # 等待线程2执行完毕
```
这个示例代码中,我们实例化了一个 Event 对象,然后启动了两个线程,线程1执行一个模拟任务,执行完毕之后设置了 event,而线程2一直等待 event 被设置,一旦 event 被设置,就退出了。在这个示例中,我们可以看到在两个线程之间通过 event 来进行同步,线程2需要等待线程1执行完毕之后才能执行。
以下是一个使用 Python Queue 的实例代码。
python
import queue
# 创建一个队列,最大容量为 3
q = queue.Queue(maxsize=3)
# 向队列中添加元素
q.put(1)
q.put(2)
q.put(3)
# 获取队列中的元素,并打印队列长度
print(q.get())
print(q.get())
print(q.get())
print("队列长度为", q.qsize())
# 尝试向已满的队列中添加元素,结果会被阻塞
#q.put(4)
# 判断队列中是否还有元素
if q.empty():
print("队列为空")
else:
print("队列不为空")
```
输出结果为:
```
1
2
3
队列长度为 0
队列为空
```
代码中我们创建了一个最大容量为 3 的队列,并向其中添加了 3 个元素,然后依次获取了队列中的元素,并打印了队列的长度。最后判断队列是否为空,并输出相应的信
使用Python UI编写事件
以下是一个使用Python编写事件的示例代码:
```python
import tkinter as tk
def on_button_click():
print("Button clicked")
def on_key_press(event):
print("Key pressed: " + event.char)
def on_mouse_move(event):
print("Mouse moved to: x=" + str(event.x) + ", y=" + str(event.y))
root = tk.Tk()
button = tk.Button(root, text="Click me", command=on_button_click)
button.pack()
root.bind("<Key>", on_key_press)
canvas = tk.Canvas(root, width=400, height=400)
canvas.pack()
canvas.bind("<Motion>", on_mouse_move)
root.mainloop()
```
在此示例中,有三个事件被绑定到不同的组件上:
- 当按钮被点击时,`on_button_click`函数将被调用。
- 当任何键被按下时,在窗口上调用`on_key_press`函数并打印按下的字符。
- 当鼠标移动到画布上时,`on_mouse_move`函数将被调用并打印鼠标的位置。
这只是一个简单的示例,你可以根据自己的需要编写更复杂的事件代码。
python中的with语句
with表达式其实是try-finally的简写形式。但是又不是全相同。
使用方法:
with context [as var]:
pass
其中的context是一个表达式,返回的是一个对象,var用来保存context表达式返回的对象,可以有单个或者多个返回值。
例子1:
with open('a.txt') as f:
print(f.read())
表达式open('a.txt')返回是一个_io.TextIOWrapper 类型的变量用f接收。在with语句块中就可以使用这个变量操作文件。执行with这个结构之后。f会自动关闭。相当于自带了一个finally。
但是with本身并没有异常捕获的功能,但是如果发生了运行时异常,它照样可以关闭文件释放资源。
例子2:
with open('b.txt') as f:
print(f.read())
Traceback (most recent call last):
File "E:/Python/pythoncode/lab_X/demo08.py", line 28, in <module>
with open('b.txt') as f:
FileNotFoundError: [Errno 2] No such file or directory: 'b.txt'
这个例子可以看出with没有捕获异常的功能。
例子3:
try:
with open('b.txt') as f:
print(f.read())
except Exception as e:
print("error")
输出:error
这个例子可以看出with发生了异常也会关闭程序。
Python调用C/C++动态链接库
最近需要使用Python调用C/C++功能,于是进行了一些相关调研。总体来说,Python调用C功能还算是相对比较简单,主要涉及ctypes这个函数库。
ctypes 是 Python 的外部函数库。它提供了与 C 兼容的数据类型,并允许调用C共享库中的函数。可使用该模块以纯 Python 形式对这些库进行封装。
基本数据类型的使用
ctypes定义了一些与C兼容的数据类型:
本篇主要关注跨语言调用时指针的处理方法,对于更全面的介绍,可参考:ctypes --- Python 的外部函数库 — Python 3.7.13 文档
下面用一个小例子来介绍Python调用C/C++动态库的方法。
C代码:
#include "stdio.h"
#include <iostream>
#ifdef __cplusplus
extern "C"
{
#endif
using namespace std;
// test for input char pointer
void print_string(char* str)
{
printf("This is c code: print_string().\n");
printf("%s\n", str);
}
// test for input integers and return an integer
int add_func(int a, int b)
{
printf("This is c code: add_func()\n");
return a + b;
}
// test for pointer as return value
int* get_array()
{
int *pa = new int[10];
for(int i = 0; i < 10; i++)
{
pa[i] = i;
}
return pa;
}
void free_array(int *pa)
{
if(pa)
delete [] pa;
}
#ifdef __cplusplus
}
#endif
上面测试代码定义了普通整数的计算并返回整数、输入字符指针并打印、输出整型指针、释放指针等操作。需要注意的是,由于ctypes只与C兼容,而C++因为支持函数重载而在编译时修改函数名,因此,对于C++代码,需要使用C的方式编译。不了解的同学可自行搜索extern "C"的用法,本篇不做过多展开。
将以上代码编译成动态链接库:
g++ -std=c++11 test_c.c -shared -fPIC -o test_c.so
接着,我们使用Python来调用该动态库。Python代码:
#!/usr/bin/python
from ctypes import *
import os
# Load dynamic library
#lib_path = os.getcwd() + '/test_c.so'
lib_path = './test_c.so'
solib = cdll.LoadLibrary(lib_path)
# Indicate the function arguments type and return value type
solib.print_string.argtypes = [c_char_p]
solib.print_string.restype = c_void_p
# Call print_string function in C library
solib.print_string(b"Hello Python!")
# Call add function in C library
solib.add_func.argtypes = [c_int, c_int]
solib.add_func.restype = c_int
sum = solib.add_func(100,200)
print('Python code: sum = {}'.format(sum))
# Call get_array function in C library, the return value is a pointer of integer
solib.get_array.restype = POINTER(c_int)
p_array = solib.get_array()
int_array = [p_array[i] for i in range(10)]
print("Python code: ")
for x in int_array:
print(x, end = ' ')
# Free the pointer
solib.free_array.argtypes = [POINTER(c_int)]
solib.free_array.restype = c_void_p
solib.free_array(p_array)
print('\nEnd Python')
运行结果:
在Python代码调用C动态库时,C库函数的参数和返回值必须是ctypes类型,参数类型使用关键字argtypes定义,对参数的定义必须是以序列的形式,如上面代码中的参数类型定义:
solib.add_func.argtypes = [c_int, c_int]
solib.print_string.argtypes = [c_char_p]
返回值参数类型使用restype定义,如上面代码中的语句:
solib.add_func.restype = c_int
solib.get_array.restype = POINTER(c_int)
其中,get_array函数的返回值使用POINTER(c_int)关键字定义成了int型的指针。
用户自定义类型的使用
除了基本数据类型,用户还可以使用自定义类型,下面给出一个自定义结构体的测试例子:
C代码:
typedef struct _point
{
int x;
int y;
char desc[50];
}Point;
int get_point(Point point)
{
printf("x = %d, y = %d, desc = %s\n", point.x, point.y, point.desc);
return 0;
}
Python代码:
class Point(Structure):
_fields_ = [
("x", c_int),
("y", c_int),
("desc", c_char * 50)
]
pt = Point(5, 10, b'I am a point.')
print(pt.x, pt.y, pt.desc)
solib.get_point.argtypes = [Point]
solib.get_point.restype = c_int
solib.get_point(pt)
Python中定义结构体时,必须继承Structure类,其成员的定义必须使用_fields_属性,否则无法调用C结构体。_fields_属性是一个list,其成员均为2个值的tuple,分别对应结构体成员的名称(C结构体成员名称)和类型,类型为ctypes类型,或者是由ctypes组合而成的新类型(如自己定义的结构体)。
以上代码的运行结果:
字符指针及数组类型
c端代码:
void arrayTest(char* pStr, unsigned char* puStr)
{
cout << pStr << endl;
cout << puStr << endl;
for(int i = 0; i < 10; i++)
printf("%c ", puStr[i]);
printf("\n");
}
python端代码:
# python2默认都是ASCII编码,python3中str类型默认是Unicode类型,而ctypes参数需传入bytes-like object。因此python3中的字符串都需要转换编码
def c_array_test():
library.arrayTest.argtype = [c_char_p, POINTER(c_ubyte*16)]
library.arrayTest.restype = c_void_p
# create_string_buffer函数会分配一段内存,产生一个c_char类型的字符串,并以NULL结尾
# create_unicode_buffer函数,返回的是c_wchar类型
str_info = create_string_buffer(b"Fine,thank you")
# from_buffer_copy函数则是创建一个ctypes实例,并将source参数内容拷贝进去
u_str_info = (c_ubyte*16).from_buffer_copy(b'0123456789abcdef')
library.arrayTest(str_info, byref(u_str_info))
指针
从上面的表格中,我们可以看到char*和void*已经有专用类型了,直接使用即可,对于其他类型的指针,ctypes提供了两种定义方式pointer和POINTER。POINTER必须传入ctypes类型,创建出新的ctypes指针类型(pointer type),而pointer传入一个对象,创建出一个新的指针实例。(POINTER创建出了pointer)。
传输地址,ctypes提供了byref函数,ctypes.byref(obj[, offset]),该函数返回一个指向ctypes实例对象的轻量级指针,函数中还可以通过参数(必须是int)来设置偏移地址,这个返回的对象只能用于外部函数调用的参数。
C端代码:
void pointerTest(int* pInt, float* pFloat)
{
*pInt = 10;
*pFloat = 12.34;
}
python端代码:
def c_pointer_test():
library.pointerTest.argtypes = [POINTER(c_int), POINTER(c_float)]
library.pointerTest.restype = c_void_p
int_a = c_int(0)
float_b = c_float(0)
# byref()函数用于传输地址
library.pointerTest(byref(int_a), byref(float_b))
print("out_a:", int_a.value)
print("out_b", float_b.value)
外部传输字符空间,在函数内部进行操作
C端代码:
void mallocTest(char* pszStr)
{
strcpy(pszStr, "Happay Children's day");
}
python端代码:
# 外部传输地址空间,在函数内部进行操作
def c_malloc_test():
library.mallocTest.argtypes = [c_char_p]
library.mallocTest.restype = c_void_p
word = (c_char * 32)()
library.mallocTest(word)
print("out_word:", word.value)
结构体
结构体是C/C++中常用类型,使用前要先定义其成员类型,在python中也是同样处理,python中的结构体必须继承Structure类,定义其成员必须使用_field_属性。该属性是一个list,其成员都是2个值的tuple,分别是每个结构体成员的类型和长度,而且定义类型必须使用ctypes类型或者由ctype组合而成的新类型。
C端代码:
//结构体
typedef struct _rect
{
int index;
char info[16];
} Rect;
python端代码:
class Rect(Structure):
_fields_ = [
('index', c_int),
('info', c_char * 16)
]
(1)读取结构体
c端代码:
int readRect(Rect rect)
{
printf("value===========================\n");
printf("index:%d info:%s\n",rect.index, rect.info);
return 0;
}
python端代码:
def c_read_rect():
library.readRect.argtypes = [Rect]
library.readRect.restype = c_void_p
rect_a = Rect(10, b"hello")
library.readRect(rect_a)
(2)读取结构体,传参为结构体指针
C端代码:
int readRectPoint(Rect* pRect)
{
printf("value===========================\n");
printf("index:%d info:%s\n",pRect->index, pRect->info);
return 0;
}
python端代码:
def c_read_rect_point():
library.readRectPoint.argtypes = [POINTER(Rect)]
library.readRectPoint.restype = c_void_p
rect_a = Rect(10, b"hello")
library.readRectPoint(byref(rect_a))
(3)传输结构体数组给动态库,实质是传输结构体数组指针,也就是首元素指针
C端代码:
void readRectArray(Rect* pRectArray)
{
for(int i = 0; i < 5; i++)
printf("RectArray[%d], index:%d, info:%s\n", i, pRectArray[i].index, pRectArray[i].info);
}
python端代码:
def c_read_rect_array():
library.readRectArray.argtypes = [POINTER(Rect)]
library.readRectArray.restype = c_void_p
rect_array = (Rect * 5)()
for i in range(5):
rect_array[i] = Rect(i, bytes("Hello_" + str(i), encoding='utf-8'))
# 以下两种方法皆可
# library.readRectArray(rect_array)
library.readRectArray(byref(rect_array[0]))
(4)从动态库中获取结构体数组内容
C端代码:
Rect* obtainRectArray(int *pArrayNum)
{
int num = 5;
*pArrayNum = num;
Rect* pArray = (Rect*)malloc(num*sizeof(Rect));
for(int i = 0; i < num; i++)
{
pArray[i].index = i;
sprintf(pArray[i].info, "%s_%d", "hello", i);
}
return pArray;
}
void freeRect(Rect* pRect)
{
free(pRect);
}
python端代码:
def c_obtain_rect_array_and_free():
library.obtainRectArray.argtypes = [POINTER(c_int)]
library.obtainRectArray.restype = POINTER(Rect)
library.freeRect.argtypes = [POINTER(Rect)]
library.freeRect.restype = c_void_p
num = c_int(10)
rect_pt = library.obtainRectArray(byref(num))
print("num:", num.value)
# 结构体数组初始化
# rect_pt.contents只能输出首元素的内容,rect_pt.contents.index
rect_array = [rect_pt[i] for i in range(num.value)]
for item in rect_array:
print("index:", item.index, "info:", item.info)
library.freeRect(rect_pt)
(5)嵌套结构体数组的处理
C端结构体定义:
struct UserStruct
{
long user_id;
char name[21];
};
struct CompanyStruct
{
long com_id;
char name[21];
UserStruct users[100];
int count;
};
python端结构体定义:
class UserStruct(Structure):
_fields_ = [
('user_id', c_long),
('name', c_char * 21)
]
class CompanyStruct(Structure):
_fields_ = [
('com_id', c_long),
('name', c_char * 21),
('users', UserStruct * 100),
('count', c_int)
]
对于python而言嵌套的自定义结构体跟普通类型一样处理。
C端函数实现:
void Print_Company(CompanyStruct* com)
{
cout << com->com_id << "," << com->name << "," << com->count << endl;
for(int i = 0; i < com->count; i++)
{
cout << com->users[i].user_id << "," << com->users[i].name << endl;
}
memset(com, 0, sizeof(CompanyStruct));
com->com_id = 1001;
strncpy(com->name, "esunny_sh", sizeof(com->name));
com->count = 10;
for(int i = 0; i < com->count; i++)
{
com->users[i].user_id = i;
char key[21] = {0};
snprintf(key, sizeof(key), "user_%d", i);
strncpy(com->users[i].name, key, sizeof(com->users[i].name));
}
}
python端函数实现:
def c_print_company():
library.Print_Company.argtypes = [POINTER(CompanyStruct)]
library.Print_Company.restype = c_void_p
user_array = (UserStruct * 100)()
for i in range(5):
user_array[i] = UserStruct(i, bytes("user_" + str(i), encoding='utf-8'))
company = CompanyStruct(1, b"esunny", user_array, 5)
library.Print_Company(byref(company))
print(company.com_id, company.name, company.count)
for i in range(company.count):
print(company.users[i].user_id, company.users[i].name)
这里需要注意初始化Company结构体时用到的user_array,user_array声明必须跟结构体中声明的长度一致。
可见传入的company结构体指针可以在动态库输出,并且动态库做的修改可以传出到python端。
Python Tkinter GUI编程
上一篇:Python项目实操笔记
下一篇:MicroPython使用