6.数据类型

予早 2024-10-05 10:16:34
Categories: Tags:

数据类型

分类

bytearray、byte

基本引用类型:
空引用:
    None	不可变
数字:
    bool	不可变
    int		不可变
    flout	不可变
    complex	不可变
序列:
    str字符串		有序   不可变     可重复
    tupl元组		有序    不可变    可重复
    list列表		有序    可变      可重复
散列:
    dict字典      无序    可变      不可重复(指key)  {1:1, 2:2, 3: 3}
    set集合       无序    可变      不可重复   {1:?, 2:?, 3: ?}

直接与间接

Python中一切皆对象,一切皆为引用数据类型,内置六大类引用类型,数字类型、字符串类型、元组类型、列表类型、字典类型、集合类型

可变与不可变

# 不可变类型不可原地修改
a = 1  # a指向目标数据1的内存
id(a)  # a指向的地址为140720495850280
b = a + 1 # b指向a+1的结果的内存
print(b)  # 2为b指向的目标数据
id(a)  # 140720495850280 a+1并未改变a指向的内存地址
id(b)  # 140720495850312 b指向新开辟的存储a+1结果的内存地址,若非如此id(a)应当与id(b相等)
# 可变类型可以原地修改
a = [1]  # a指向[1]的内存
id(a)  # 2955498803968
a[0] = 2  # 修改a中第一个元素的值
print(a)  # [2]
id(a)  # 2955498803968

# 可变类型可以不原地修改
a = [1]
id(a)  # 2955498788416
a = a + [1]
print(a)  # [1, 1]
id(a) ## 2955498806720

字节类型

s = b"yuzao"
print(s, type(s))
print(s.__sizeof__())
print(s.__len__())

数字类型,Number

不可变类型

整型

# <class 'int'>
print(type(999))  # 十进制整型
print(type(0b1010))  # 二进制整型

Python中整型取值范围无限制

浮点型

# <class 'float'>
print(type(3.1415926))  # 浮点数
print(type(3.1415926e2))  # 科学计数法浮点数

浮点数取值范围约±10^308

# 计算机中无法精确表示所有浮点数,这是由浮点数存储方案决定的系统误差,要以有限空间尽可能存储无限的浮点数是要做取舍的
a = 0.1
b = 0.2
print(a + b)
# 0.30000000000000004

布尔型

# <class 'bool'>
from numbers import Number
print(issubclass(bool, Number))  # T
print(type(True))  # <class 'bool'>
print(type(False))  # <class 'bool'>
print(True == 1)  # True
print(True == 2)  # False
print(False == 0)  # True
print(False == 2)  # False

复数

# <class 'complex'>
print(type(3-3j))
print(type(complex(3,-3)))
z = 1 + 3j
z.real
z.imag

字符串类型

不可变类型,字符串是若干字符的有序序列。

注:Python3字符集默认使用Unicode,编码方式默认使用UTF-8。Python2字符集默认使用ASCII,编码方式采用ASCII简易映射,Python2版本常在文件首行附加# -\*- coding: UTF-8 -\*-注释用以显式指定编码方式,Python3版本代码无需指定。

字符串字面量

Python中单引号和双引号的等价的。

字符串操作符

字符串操作符 含义
+ 字符串连接符
* 字符串复制符
in 子串判断符
string[x] 获取第x-1个字符
string[S:E:L] 从[S, E)按照L的步长切片,L可为附属
# 步长超过字符串总长度会返回S位置上的字符
a = "0123456789"
a[::100]
# '0'

# 字符串可以使用r不进行转义,保留原始字符串

字符串操作函数

字符串操作函数 含义
len(x) 返回字符串x的长度
str(x) 返回任意类型x对应的字符串形式,str(1.23)结果为”1.23”,str([1,2])结果为”[1,2]”
eval(expression) eval() 函数用来执行一个字符串表达式,并返回表达式的值。eval(‘print(‘hello’)’),结果为hello
hex(x) 返回整数x的十六进制小写形式字符串
oct(x) 返回整数x的八进制小写形式字符串

字符串处理方法

字符串处理方法 含义
string.lower() 返回字符串副本,全部字符小写
string.upper() 返回字符串副本,全部字符大写
string.split(sep=None) 返回一个列表,由string根据被分隔的部分组成,”A,B,C”split(“,”)结果为[‘A’,’B’,’C’]
string.count(sub) 返回字串在string中出现的次数,”aaa”.count(“aa”)结果为1
string.replace(o;d,new) 返回字符串副本,所有old字串被替换为new
string.center(width[,fillchar]) 字符串根据宽度width居中,filler可缺省
string.strip(chars) 在string左侧和右侧去掉chars中列出的字符,逐一去除直至非chars所列字符
string.join(iter) 在字符串中相邻两个字符之间增加字符串string

格式字符串

Format Specification Mini-Language

https://docs.python.org/3/library/string.html#format-string-syntax

# f-str
print(f'予早个人blog,技术碎碎念,主要语言为{None}、{{1, 2, 3}}、{"{Go}"},包含前端、后端、AI、算法、测试、运维等内容')
# format-str
# format-str会将对象按照一定规则转为字符串并填充到模板中
# {field_name[!conversion][:format_pecification]}

# 默认位置方式
print('予早个人blog,技术碎碎念,主要语言为{}、{}、{},包含{}、{}、{}、{}、{}、{}等内容'.format(
    3.14, ["Java", 0], None, b"front_end", r"后端\n", True, {"算法": False}, ("测试",), {}
))

# 指定位置方式
print('予早个人blog,技术碎碎念,主要语言为{2}、{1}、{1},包含前端、后端、AI、算法、测试、运维等内容'.format(
    'Python', 'Java', 'Go'
))

# 指定名称方式
print('予早个人blog,技术碎碎念,主要语言为{v1}、{v1}、{v3},包含前端、后端、AI、算法、测试、运维等内容'.format(
    v1='Python', v2='Java', v3='Go'
))

# 默认位置方式和指定名称方式可以混用,指定位置方式只能单独使用
print('予早个人blog,技术碎碎念,主要语言为{}、{}、{v1},包含{v2}、后端、AI、算法、测试、运维等内容'.format(
    'Python', 'Java', v1='Go', v2="前端"
))


# 符号设置
# 给数据加前置符号。可选为+、-、space
print('{:+}'.format(520))    # +520 正数可以加+
print('{:-}'.format(520))    # 520  正数不会加-
print('{: }'.format(520))    #  520 整数可加空格,能与负数对齐
print('{:+}'.format(-520))   # -520 复数不会加+,因为有-
print('{:-}'.format(-520))   # -520 复数不会加-,因为有-
print('{: }'.format(-520))   # -520 复数不会加空格,因为有-
print('{: ,}'.format(5200))  #  5,200

# 分组设置
print('{:,}'.format(5200))  # 5,200
print('{:_}'.format(5200))  # 5_200


# 对齐设置
print('{:6}'.format(520))
print('{:=6}'.format(520))
print('{:>6}'.format(520))
print('{:<6}'.format(520))
print('{:^6}'.format(520))

print('{:06}'.format(-520))
print('{:0=6}'.format(-520))
print('{:0>6}'.format(-520))
print('{:0<6}'.format(-520))
print('{:0^6}'.format(-520))

# print('{:06}'.format( 'Python'))  # ValueError: '=' alignment not allowed in string format specifier
# print('{:0=6}'.format('Python')) # ValueError: '=' alignment not allowed in string format specifier
print('{:0^6}'.format('yz'))
print('{:0>6}'.format('yz'))
print('{:0<6}'.format('yz'))
print('{:0^6}'.format('yz'))


# 类型设置
print('{0:b} {0:#b}'.format(520))  # 二进制
print('{0:o} {0:#o}'.format(520))  # 八进制
print('{0:d} {0:#d}'.format(520))  # 十进制
print('{0:x} {0:#x} {0:#X} {0:#X}'.format(552200))  # 十六进制

print('{:c}'.format(80))  # P 80的Unicode字符

print('{:e}'.format(3.14))  # 3.140000e+00 科学计数法,精度默认为精确到小数点后6位
print('{:E}'.format(3.14))  # 3.140000E+00 科学计数法,精度默认为精确到小数点后6位
print('{:f}'.format(3.14))  # 3.140000 f将参数以定点法的形式输出(不是数用nan标示,无穷用inf标示,默认精度为6)
print('{:F}'.format(3.14))  # 3.140000 F将参数以定点法的形式输出(不是数用NAN标示,无穷用INF标示,默认精度为6)
print('{:g}'.format(3.14))  # 通用浮点类型
print('{:g}'.format(31457788))  # 通用浮点类型
print('{:%}'.format(0.89))  # 89.000000% 百分数,精度默认为精确到小数点后6位


# 精度设置
print('{:.2f}'.format(3.1415))  # 3.14,小数点后的位数为2
print('{:.2g}'.format(3.1415))  # 3.1,小数点前后总位数为2
print('{:.6s}'.format('i love you'))  # i hate,总位数6

import decimal
print("{:,}".format(decimal.Decimal("{:.2f}".format(1))))
print("{:,}".format(decimal.Decimal("{:.2f}".format(decimal.Decimal("1231231.3252")))))
"""
字符串
"""
s = "  davis JoNes_aBc  "
print(s.capitalize())
print(s.upper())
print(s.lower())
print(s.swapcase())
print(s.title())
print(s.startswith("Da"))
print(s.endswith("Bc"))
print(s.count("a"))
print(s.find("a"))  # 找不到返回-1
print(s.find("aB"))
print(s.replace('davis', 'DAVIS'))
print(s.index("JoNes"))  # 找不到抛出异常
print(s.join("      "))
print(s.strip())
print(s.strip(" "))
print(s.rstrip(" "))
print(s.lstrip(" "))
print(s.split())
print(s.split(" "))
print(s.split("a"))

s = ”Hello World“

print(s[3])
print(s[2:6])
print(s[::])
print(s[::-1])
# 字符串索引切片

# 字符串与列表相互转换,join、split
print(' '.join(['1', '2', '3', '4', '5']))

# 字符串%格式化输出,仅有%s、%d
name = input("请输入姓名:")
age = input("请输入年龄:")
process = input("请输入学习进度:")
msg = "我是%s,今年%s岁,学习进度为%s%%" % (name, age, process)  # 前面%为转义标识,即%%输出%
print(msg)
# 正则表达式
# python内置模块

# re
import re

pattern = ""
str_ = ""

result = re.search(pattern, str_)
print(result.group() if result else None)

result = re.match(pattern, str_)  # 必须从头匹配
print(result.group() if result else None)

result = re.findall(pattern, str_)
print(result)

result = re.finditer(pattern, str_)  # 找的内容比较多的时候
for i in result:
    print(i.group() if i else None)

result = re.split(pattern, str_)

result = re.sub(pattern, 'O', str_)
print(result)
obj = re.compile(pattern)
result = obj.search(str_)
print(result)

pattern = "/\b[\w.%+-]+@[\w.-]+\.[a-zA-Z]{2,6}\b/g"
str_ = "abcd test1@jld.com 1234 test2@jld.com"
result = re.search(pattern, str_)
print("---", )
print(result.group() if result else None)

# ()表示捕获分组,() 会把每个分组里的匹配的值保存起来,python分组优先加?
import string

print(string.whitespace)  # whitespace = ' \t\n\r\v\f' 空格 水平制表符 换行符 回车符 垂直制表符 换页符
print(string.ascii_lowercase)  # abcdefghijklmnopqrstuvwxyz
print(string.ascii_uppercase)  # ABCDEFGHIJKLMNOPQRSTUVWXYZ
print(string.ascii_letters)  # abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
print(string.digits)  # 0123456789
print(string.hexdigits)  # 0123456789abcdefABCDEF
print(string.octdigits)  # 01234567
print(string.punctuation)  # !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
print(string.printable)  # digits + ascii_letters + punctuation + whitespace

# whitespace -- a string containing all ASCII whitespace
# ascii_lowercase -- a string containing all ASCII lowercase letters
# ascii_uppercase -- a string containing all ASCII uppercase letters
# ascii_letters -- a string containing all ASCII letters
# digits -- a string containing all ASCII decimal digits
# hexdigits -- a string containing all ASCII hexadecimal digits
# octdigits -- a string containing all ASCII octal digits
# punctuation -- a string containing all ASCII punctuation characters
# printable -- a string containing all ASCII characters considered printable


print(string.capwords("hello world"))  # Hello World

# Template


# Formatter

字符串判断是否是数字

isalnum

是否为字母数字字符串,字符串中所有字符为字母或者数字,且至少有一个字符,则为True,否则为False

字母数字字符 c 判定条件,四者任一为True即可:

isalpha

str.isalpha()

是否为字母字符串。若字符串中所有字符均为字母且至少有一个字符,则为True,否则为False。

Note that this is different from the Alphabetic property defined in the section 4.10 ‘Letters, Alphabetic, and Ideographic’ of the Unicode Standard.

isdecimal、isdigit、isnumeric

c.isdecimal()

是否为十进制字符构成的字符串。若字符串中所有字符均为十进制数字且至少有一个字符,则为True,否则为False

十进制字符是 Unicode 常规类别“Nd”中的字符

str.isdigit()

从形式上讲,数字是属性值为 Numeric_Type=Digit 或 Numeric_Type=Decimal 的字符。

str.isnumeric()

从形式上讲,数字字符是属性值为 Numeric_Type=Digit、Numeric_Type=Decimal 或 Numeric_Type=Numeric 的字符。

# 测试字符串
test_str = (
    # 数字字符构成的字符串
    "1234",  # 十进制数字
    "¹²³",  # 上角标整数
    "¼2½",  # 上角标分数
    "1234",  # 全角数字
    "ⅠⅡⅢⅣⅤ",  # 罗马数字
    "①②③④⑤",  # 序号数字
    "一二三四",  # 汉字数字
    
    # 数字字符和其他字符构成的字符串
    "12.34",  # 小数
    "1/3",  # 分数
    "0b1011",  # 二进制数字
    "0xABCD",  # 十六进制数字
)


print(f"{'string':<10}: {'isdecimal':<10} {'isdigit':<10} {'isnumeric':<10}")
for s in test_str:
    print(f"{s:<10}: {s.isdecimal():<10} {s.isdigit():<10} {s.isnumeric():<10}")
string    : isdecimal  isdigit    isnumeric 
1234      : 1          1          1         
¹²³       : 0          1          1         
¼2½       : 0          0          1         
1234    : 1          1          1         
ⅠⅡⅢⅣⅤ  : 0          0          1         
①②③④⑤      : 0          1          1         
一二三四    : 0          0          1         

12.34     : 0          0          0         
1/3       : 0          0          0         
0b1011    : 0          0          0         
0xABCD    : 0          0          0   

通用正则

整数

r"^[+-]?0$|^[+-]?[1-9]\d*$"

小数

^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$

元组类型,Tuple

不可变类型,列表是若干元素的无序序列。

<class 'tuple'>
# 定义方式
a = (1, 2, 3)
b = tuple([1, 2, 3])
# 元组字面量
a = (1, 2, 3)  # 标准形式
b = (1,)  # 单一元素需要加,与(1)区分,(1)与1是等价的
c = 1, 2, 3  # 可省略小括号,函数返回值即为元组类型,通常不加小括号
d = 1,  # 添加,与整型1区分
"""
元组
"""
t = (1, 2, 3, 'tuple', [1, 'tuple'])
t[4][0] = 2
print(t)

列表类型,List

可变类型

# 定义方式
a = [1,2, 3]
b = list([1, 2, 3])
# 列表字面量
a = [1, 2, 3]
b = [
    "12",
    "21"
    "1e",
    "er"
]  # 实际上只有三个元素,['12', '211e', 'er']
"""
列表
"""
l = [1, 2, 3]
# 索引切片同字符串,增删改查
l.append('4')
l.pop(-1)
l.extend((1, 2, 3))
l.remove(1)
l.clear()

l[0:1] = '123457890'  # 根据切片修改,有多少改多少
print(len(l))
l.sort(reverse=True)
l.reverse()

列表操作符

列表操作符 含义
ls[i] = x 替换列表ls第i位元素为x
ls[i:j:k] = lt 用列表lt替换ls切片后多对应的子元素列表
ls += lt 更新列表ls,将列表lt中的元素增加到列表ls中
ls *= n 更新列表ls,将其元素重复n次

列表操作函数

列表操作函数 含义
del ls[i] 删除ls列表中第i元素
del ls[i:j:k] 删除列表ls中第i到j以k为步长的元素

列表处理方法

列表处理函数 含义
ls.append(x) 在列表ls最后增加一个元素x
ls.clear() 删除列表中所有的元素
ls.copy() 生成一个新的列表,赋值ls中所有的元素
ls.insert(i,x) 在列表的第i位置增加元素x
ls.pop(i) 将列表ls中第i位置元素返回并删除该元素
ls.remove(x) 将列表ls中出现的第一个元素x删除
ls.reserve() 将列表ls中的元素反转

字典类型,Dictionary

可变类型,字典是若干键值对组成的整体,key不允许重复,key为任意不可变类型

a = {1: "A", "c": None, (1, 2): [0]}
b = dict([(1, 2), [2, 3], {3,4}])  # 容器相对自由
"""
字典
"""
d = {'1': 1, '2': 2, '3': 3}
a = [1]
d = {a: 12}
a = 2
print(d)

# 字典的key需要是基本数据类型?
# 增
d[2] = 2
# 删
d.keys()
d.values()
d.copy()
d.clear()
d.get(1, 'NULL')
k, v = d.items()
d.setdefault(1, 12)  # 有键值对不更改,无则使用值更改
d.pop(100, '123')
d.popitem()  # 随机删除
d2 = {1: 2, 4: 4}

d.update(d2)  # 字典更新

a, b = 1, 2
b, a = a, b

# builtins

字典合并

d1 = {"A": 1, "B": 2, "C": 3}
d2 = {"B": 4, "C": 5, "D": 6}
print({**d1, **d2})
print(d1 | d2)
d = {'hash': 'bang', 'slash': 'dot'}
d = dict(hash='bang', slash='dot')
d = dict({'hash': 'bang', 'slash': 'dot'})
d = dict([['hash', 'bang'], ['slash', 'dot']])

直接赋值的x
from timeit import timeit
timeit("a = {'a': 1, 'b': 2}")
0.424...
timeit("a = dict(a = 1, b = 2)")
0.889...

注:

  1. Python3.7以前,dict中键值对的插入顺序和存储顺序不一致,通常使用OderedDict保证插入和存储顺序的一致,Python3.7及之后,dict默认键值对插入顺序和存储顺序一致。
  2. 字典key使用.操作,则需要实现重写__getattr__方法

字典类型操作符

字典类型操作符 含义
k in d 返回boolean,判断k键是否在字典d中
d[k] 获取k对应的v,若没有对应的k则报错
d[k] = v 将k对应的值修改为v,没有k就创建键值对
d3 = d1 | d2 将两个字典合并生成一个新的字典,注意,是浅拷贝的合并,d3是一个新字典,同key会被覆盖,右边覆盖左边

PEP 584

字典合并符号并不高效,d | e | f | g | h 会创建和销毁三个临时映射。

序列级联的每一次合并都会使序列中的元素总数增加,最终会带来 O(N^2) 的性能开销。而字典合并有可能会有重复键,因此临时映射的大小并不会如此快速地增长。

正如我们很少将大量的列表或元组连接在一起一样,PEP的作者任务合并大量的字典也是少见情况。若是确实有这样的诉求,那么最好使用显式的循环和就地合并:

new = {}
for d in many_dicts:
    new |= d
d1 = {1: 1, 2: 2, 3: 3, 4: 4, 5: 5}
d2 = {1: 2, 3: 4, 5: 6, 7: 8, 9: 0}

d3 = d1 | d2
print(d1, d2, d3)
print(id(d1), id(d2), id(d3))

d1 |= d2
print(d1)
print(id(d1))

字典类型操作函数

字典类型操作函数 含义
del d[k] 删除字典d中键k对应的键值对
len(k) 返回字典中元素的个数

字典类型处理方法

字典类型处理方法 含义
d.keys() 返回字典d中所有键的信息
d.values() 返回字典d中所有值的信息
d.items() 返回字典d中所有键值对的信息
dict.get(key[, value]) 若键k存在,返回相应值,反之返回
d.pop(k[, value]) 若键k存在,返回并删除相应值,反之返回
d.popitem() 随机从字典d中以元组形式返回并删除一个键值对
d.clear() 删除字典d中所有键值对
d.setdefault(k, default=None) 若字典中没有k,则为k设置默认值

集合类型,Set

可变类型,集合是若干无序唯一元素组成的整体,集合中的元素都是不可变类型

a = {1, 2, 3} # 集合没有空集合字面量,不同于()、[]、{}
b = set([1, 2, 3])
"""
集合
"""
s = {1, 2, 3}
# frozenset

集合操作符

集合操作符 含义
S | T 并,返回一个集合,包含S、T所有元素
S - T 差,返回一个集合,包含在S但不在T中的元素
S & T 交,返回一个集合,包含S、T都有的元素
S ^ T 返回一个集合,包含S、T中互不相同的元素
S <=T 或 S<T 返回boolean,判断S和T的子集关系
S>=T 或 S>T 返回boolean,判断S和T的包含关系
S |= T 更新集合S,包括在集合S和T中的所有元素
S -= T 更新集合S,包括在集合S但不在T中的元素
S &= T 更新集合S,包括同时在集合S和T中的元素
S ^= T 更新集合S,包括集合S和T中非相同的元素

集合操作函数

集合操作函数 含义
len(s) 返回集合s的元素个数
x in s 返回boolean,判断x是否在集合s中
x not in s 返回boolean,判断x是否不在集合s中
set(x) 将其他变量x转换为集合类型

集合处理方法

集合处理方法 含义
s.add(x) 若x不在集合中,将x增加到s
s.discard(x) 移除s中的元素x,若x不在集合s中,不报错
s.remove(x) 移除s中的元素x,若x不在集合s中,产生KeyError异常
s.clear() 移除s中所有元素
s.pop() 随机返回s的一个元素并更新s,若s为空,产生KeyError异常
s.copy 返回集合的一个副本

数字操作

函数 含义
abs(x) x的绝对值
divmod(x,y) 商余,(x//y,x%y),同时输出商数和余数
pow(x,y[,z]) 幂余,(x**y)%z,参数z可缺省
round(x[,d]) 四舍五入,d是保留小数位数,默认值为0
max(x1,x2,x3,…,xn) 最大值,n不限
min(x1,x2,x3,…,xn) 最小值,n不限
int(x) 将x变为整数,舍弃小数部分,非四舍五入,int(123.5)==123,int(“123.5”)==123
float(x) 将x变为浮点数,增加小数部分,int(123)==123.0,int(“123”)==123.0
complex(x) 将x变为复数,增加虚数部分

序列操作

字符串、元组、列表均是序列。

序列类型

序列操作符

正向递增序号、反向递增序号

序列操作函数

序列处理方法

数据类型转换

# 数据类型转换

# str -> bool
# 非空字符串为真,空字符串为假

collection

from collections import Counter   #引入Counter
a = [29,36,57,12,79,43,23,56,28,11,14,15,16,37,24,35,17,24,33,15,39,46,52,13]
b = dict(Counter(a))
print ([key for key,value in b.items()if value > 1])  # 只展示重复元素
print ({key:value for key,value in b.items()if value > 1})  # 展现重复元素和重复次数
import collections

d1 = collections.OrderedDict()  # 将普通字典转换为有序字典
d1['a'] = 1
d1['b'] = 2
d1['d'] = 4
d1['c'] = 3
for k, v in d1.items():
    print(k, v)

d1 = {'a': '1', 'b': '2', 'd': '4', 'c': '3'}
d1 = collections.OrderedDict(d1)
for k, v in d1.items():
    print(k, v)
# 3.7及以后版本dict插入顺序和存储顺序一致

类型提示,type hint

Python类型提示有type annotation和type comment两种方式,类型提示与linter协同工作,实际类型与类型提示不一致不影响运行时

typing库用于类型提示

pydantic做类型提示和类型检查

https://www.cnblogs.com/popapa/p/PEP484.html

https://peps.python.org/pep-0563/

Type Annotation

:语句将信息附加到变量或函数参数中,->运算符用于将信息附加到函数/方法的返回值中

import math

def circumference(radius: float) -> float:
    return 2 * math.pi * radius
print(circumference.__annotations__)

def test(request_data: Any):
    pass

from typing import Union
from typing import Optional


def f(l1: Optional[int] = None, l2: Union[int, str, None] = None):
    """
    Optional是Union的特例
    :param l1:
    :param l2:
    :return:
    """
    print(l1, l2)

注:

  1. type annotation方式会导入所有类型提示中使用到的类型依赖,即使运行时中不会用到。
  2. 另外复合类型如List[str],解释器在首次加载文件时会执行一些操作构造该类型,Python 3.7时引入了 PEP-563 ~ postponed evaluation of annotations,使用from __future__ import annotations避免类型构造

泛型类型提示

 """
 Python 的类型提示基于泛型,简称泛型类型提示,静态检查工具基于泛型类型提示进行检查,解释器不会检查
 """
 
 from typing import Generic, TypeVar, List
 
 T = TypeVar('T')  # 泛型类型变量T
 
 
 class MyGenericClass(Generic[T]):  # 泛型类
     def __init__(self):
         self.items: List[T] = []
 
     def add_item(self, item: T):  # 泛型函数
         self.items.append(item)
 
 
 # 使用
 my_int_list = MyGenericClass[int]()
 my_int_list.add_item(1)
 my_int_list.add_item('1')  # 此处 PyCharm 会有提示
 
 print(my_int_list.items)
 # [1, '1']

Type Comment

# headlines.py
def headline(
    text,           # type: str
    width=80,       # type: int
    fill_char="-",  # type: str
):                  # type: (...) -> str
return f" {text.title()} ".center(width, fill_char)

print(headline("type comments work", width=40))

Stub FIle

Stub FIle,存根文件,以.pyi为后缀,可参考https://www.cnblogs.com/popapa/p/PEP484.html

demo.pydemo.pyi放在同一目录,在PyCharm中可以在.py.pyi文件看到变量val和函数hello所在行有一个*标记,可以点击该标记在.py.pyi之间跳转

# demo.py
val = 1


def hello(name): 
    return "Hello" + name


print(hello("World"))
print(hello(12345))  # PyCharm会报黄
# demo.pyi
val: int


def hello(name: str): ...  # 函数体通常以...来省略细节

鸭子类型

鸭子类型,不通过其本身类型判断类型,而是通过其属性、表现判断。狗拿耗子,狗即为猫。

types

types,类型库,Python标准库

动态创建模块

import types

m = types.ModuleType("config")


def get_version():
    print("mouse.bull.mouse")


setattr(m, "get_version", get_version)

print(m, type(m), m.__dict__)

m.get_version()  # mouse.bull.mouse

代码分析

遍历元素性能分析

import time

l1 = list(range(10000))

t = time.perf_counter()

for i in range(10000):
    if i in l1:
        ...

print(time.perf_counter() - t)
# 0.6000013

l2 = set(range(10000))

t = time.perf_counter()

for i in range(10000):
    if i in l2:
        ...

print(time.perf_counter() - t)
# 0.0009529999999999816

迭代器切片

import itertools

# 与slice()区分
l1 = range(40, 50)
l11 = l1[2:30]
print(l11)
for i in l11:
    print(i, end=" ")
print()
for i in l1:
    print(i, end=" ")
print()

l2 = range(40, 50)
l22 = itertools.islice(l2, 2, 30)

for i in l22:
    print(i, end=" ")
print()
for i in l2:
    print(i, end=" ")
print()

# 生成的是副本
# 在 Python 中,对迭代器进行切片操作会创建一个新的迭代器,并且在对新的迭代器进行遍历时,会重新遍历整个切片范围内的元素。