学习笔记——Python3

一切都是对象

Posted by 大攀 on Thursday, November 19, 2020

TOC

python个人日常测试库,其中也有一些记录文档:https://github.com/xumamba/python-common

语法基础

对象

  每个值都有具体的内容和类型,计算机要表示这个值,就需要给这个值分配一块独立的存储空间。在Python中用对象来刻画有独立内存空间和数据类型的值,程序中的数据都是以对象的形式存在的。

  一个对象包含一个具体数据的三个特征:值、数据类型、id(该对象的内存地址)。内置函数type()和id()查询一个对象的数据类型和id。

  None是一个没有值的空值对象。变量是对象的引用。

变量

  变量是对象的引用。

  ==运算符用于比较对象的值是否相等,is运算符用于判断两个对象是否为同一个。

  在静态类型语言中,变量是一块具有确定类型的内存的名字,一旦定义了该变量,则在销毁该变量前,其变量名始终指向这块内存。与静态类型语言不同,Python是一个动态类型语言,变量名仅是一个对象的名字,并不是占据一块内存的那个对象本身,一个变量名可以随时指向不同的对象,直到程序运行时,才能根据其指向的对象知道该对象的数据类型。

s="str" # s指向string类型的对象
s=123  # s改指向int类型的对象

类型

  数值、字符串、列表、元组、集合、字典。

  数值类型:int、float、complex、bool。

  只要计算机内存足够,Python的整型的长度就可以任意长。但浮点型的值小数点后的精度不超过15位,而复数型的值总是写成x+yi形式。

  list指定下标范围内的元素赋值一个空的list ,相当于删除这个范围内的元素。

    l = [1, 2, 3, 4]
    l[1:2] = []
    print(l) # [1, 3, 4]

  str类型的对象也是不可修改的(immutable),但是是可迭代的(iterable)。

- lstrip()、rstrip()和strip()分别用于删除字符串中的左侧、右侧和左右两侧位置的空白字符;
- split(sep=分隔符,max=最大分割次数)通过指定分隔符对字符串进行分割;
- str.join(sequence)用字符串str连接序列sequence中的其他字符串;
- replace(old, new [, max]);
- find()、index()查找是否存在匹配字符串的str子串;
- count()字串次数统计;
- format()格式化字符串;数值的格式化以:开头,后面跟一些字符,如:d表示输出十进制的整数,:f表示输出浮点数,:b、:o、:x分别表示输出的是二进制、八进制和十六进制数。

  集合是根据其元素的哈希值存储元素的,所以无法计算哈希值的对象不能作为集合的元素。

  循环语句(for或while)都可以在后面跟一个else语句,当for语句遍历完整个可迭代对象(如遍历完整个list的元素),或者当while语句的条件表达式是false退出时,都会执行这个else语句。但是,如果是通过break跳出循环语句则不会执行这个else语句。

    for i in range(5):
        print(i)
    else:
        print("for: all traversal is done")  # true
    j = 0
    while j < 5:
        print(j)
        if j == 3:
            break
        j = j + 1
    else:
        print("while: all traversal is done")  # false

  list中的元素不是对象本身而是对象的引用。无论每个对象本身占据多大内存,这个引用总是占用固定大小的内存。空的list占用64字节的内存,每添加一个元素,就多占用8字节,这8字节就是实际对象的引用所消耗的内存。

    import sys
    test_size = []
    print(sys.getsizeof(test_size))  # 64
    test_size = [2]
    print(sys.getsizeof(test_size))  # 72
    test_size = [2, 3.14]
    print(sys.getsizeof(test_size))  # 80
    test_size = [2, 3.14, 'hello']
    print(sys.getsizeof(test_size))  # 88
    test_size = [2, 3.14, 'hello', [5, 6.7]]
    print(sys.getsizeof(test_size))  # 96
    
    # 使用append和insert底层数组会一次性扩容,并且insert指定越界的索引位置插入,会插入成功。此处实际插入索引为5。 
    test_size.append('extra')
    print(sys.getsizeof(test_size))  # 128
    test_size.insert(8, 'cross border')
    print(sys.getsizeof(test_size))  # 128

函数

在函数内部使用全局变量,需要在函数内部对全局变量加以global修饰。

嵌套函数不能修改包围环境中的变量,除非该变量在嵌套函数中被声明为nonlocal

函数默认形参只在函数定义时计算一次!每次函数调用这个默认形参时,始终指向的都是同一个初始化对象。

    def f(var, arr=[]):
        arr.append(var)
        return arr
    print(f(1))  # [1]
    print(f(2))  # [1, 2] 
    iterator = map(lambda x: x ** 2, [1, 2, 3, 4])
    print(iterator)  # <map object at 0x0000022D32C10EF0>
    print(list(iterator))  # [1, 4, 9, 16]
    
    print(tuple(map(lambda x, y: x * y, [1, 2, 3], [4, 5, 6, 7])))  # (4, 10, 18)
    
    print(list(filter(lambda x: x > 0, range(-5, 5))))  # [1, 2, 3, 4]
    import random

    src_data = [1, 2, 3, 4, 5, 6]
    random.shuffle(src_data)
    print(src_data)
    print(random.sample(src_data, 3))

    random.seed(1)
    test_seed = lambda: random.sample(range(-5, 5), 3)
    print(test_seed())  # [-3, -4, -1]
    print(test_seed())  # [-4, 2, 3]

    # 随机数发生器必须放在函数内部
    def f():
        random.seed(2)
        for i in range(5):
            print(random.random())
        for i in range(3):
            print(random.randint(-5, 5))
    f()
    f()

    def ff():
        random.seed(3)
        return random.randint(-3, 3)
    print(ff())  # -2
    print(ff())  # -2

  如果没有为一个包定义all,则当使用import *时不会导入任何对象; 如果没有为一个模块定义all,则当使用import *时将导入模块中的所有对象,否则仅导入all中定义的对象。

异步IO

  Python的异步模型是基于回调、事件、传输、协议等概念构建的“多任务合作”模式(cooperative multitasking)。只存在一个线程,不可能多个任务同时执行,多个任务分享运行时间。

asyncio API

  • import asyncio
  • async def func() 这种函数执行可以暂停,交出执行权
  • 在async函数内部的异步任务前面,加上await命令
  • async.run() 方法加载async函数,启动事件循环
import asyncio
import time


async def hello(s: int, name: str) -> None:
    print("Hello: ", name)
    await asyncio.sleep(s)
    print("Bye~: ", name)


async def main():
    start = time.perf_counter()
    await asyncio.gather(hello(2, "Jerry"), hello(2, "Tom"))    # gather将多个异步任务包装成一个新的异步任务
    print("execution time: ", time.perf_counter()-start)

asyncio.run(main())

comments powered by Disqus