《C++ Primer》第02章-变量和基本类型

2.1 基本算术类型 算术类型 空类型 类型大小说明 c++标准规定了每个类型的内存最小值,见上表。 一个int至少和一个short一样长 一个long至少和一个int一样长 一个long long至少和一个long 有符号与无符号 一个int和一个unsigned相加,会被转换成unsigned 不要混用有符号和无符号数 字符类型 wchar_t确保可以存放最大扩展字符集的任意一个字符(即取最长长度) char16_t,unicode字符,16位 char32_t, unicode字符,32位 字符串分为三种:char、signed char、unsigned char char和signed char并不一样 浮点数 float通常精度不够 双精度浮点数和单精度浮点数的计算代价相差无几 对某些机器来说,双精度浮点数和单精度浮点数的计算代价相差无几 long double的精度通常下没有必要,且它的运行时消耗不容忽视 类型转换 非布尔类型转布尔类型,若为0则为false,否则为true 布尔类型转其他类型,fasle为0,true为1 浮点数转整型时,仅仅保留浮点数小数点前的部分(做四舍五入吗?) 整型转浮点数时,小数部分为0,如果整数所占空间超过了浮点数容量,精度可能损失(??) 给无符号数赋一个超出它所表示范围的值时,结果是初始值对初始值对无符号数最大值+1取模后的余数。-1赋给unsigned char为255??? -1的表示 建议:避免无法预知和依赖于实现环境的行为 程序应该尽量避免依赖于实现环境的行为,如果把int看成一个确定不变的值,则这样的程序是不可移植的 字面值常量 字符和字符串字面值 一个字面值通常被存放在能存放其的最小的数据类型中,若一个字面值内存超过了最大能存放其的类型,则报错 字符串字面值的长度比其实际长度多1(编译其在每个字符串的结尾处添加一个空字符\0) 如果两个字符串字面值位置紧临且仅由空格、缩进、换行符分隔,则它们实际上是一个整体 转义序列 泛化转义序列,\x后加一个或多个16进制数,\后加1至3个八进制数 指定字面值的类型 例如 初始化和赋值是两个完全不同的操作 初始化是指创建变量时赋予其一个初始值 赋值的含义是把当前的值擦除,用一个新值代替。 4种初始化 1 2 3 4 int a = 0; int a = {0}; int a{0}; int a(0); 当内置类型的变量进行列表初始化时,若存在丢失信息风险,则编译器将报错...

created: 2023-04-04  |  updated: 2023-04-04  |  阿秀

《C++ Primer》第03章-字符串、向量、数组

3.1 命名空间的using声明 当使用std::string时,可以用using std::string;进行声明,然后直接访问string即可 3.2 标准类型库string 3.2.1 4种常见初始化方法 1 2 3 4 5 6 7 8 #include <iostream>using std::string; string s1 = "s1"; string s2("s2"); string s3(3, 'a'); // aaa string s4; // 初始化一个空串 3.2.2 直接初始化和拷贝初始化 3.2.3 string的操作 注意: os<<s; is>>s; getline(is, s); 执行读操作时,string对象会自动忽略开头的空白(空格符、换行符、制表符),并从第一个真正的字符开始,直到遇到下一个空白为止。 触发getline返回的那个换行符实际上被丢弃了,返回的对象中并不包含那个换行符 size_type体现了标准库类型与机器无关的特性 两个string使用+运算符后返回的是一个新的string string和字面量相加+要确保有一个string,最终被转换为string 处理string中的字符: 只要字符串不是const,则可以为下标运算返回的字符赋予新值...

created: 2023-04-04  |  updated: 2023-04-04  |  阿秀

《Fluent Python》目录

intro 《Fluent Python》这本书前大半部分不错,但偏重点是讲技巧,讲习惯,讲约定 目录索引 第01章 Python数据模型 第02章 数据结构 第03章 字典和集合 第04章 文本和字节序列 第05章 一等函数 第06章 使用一等函数实现设计模式 第07章 函数装饰器和闭包 第08章 对象引用、可变性和垃圾回收 第09章 符合Python风格的对象 第10章 序列的修改、散列和切片 第11章 接口,从协议到抽象基类 第12章 继承的优缺点 第13章 正确重载运算符 第14章 可迭代对象、迭代器和生成器 第15章 上下文管理器和else块 第16章 协程 第17章 使用concurrent.futures处理并发 第18章 使用asyncio包处理并发

created: 2023-04-04  |  updated: 2023-04-04  |  阿秀

《Fluent Python》第01章 python数据模型

namedtuple 第二个参数传入一个字符串, namedtuple将创建一个Point类,且这个类有x和y这两个属性 1 2 3 4 import collections Point = collections.namedtuple('Point', 'x y') O = Point(0, 0) print(O) 特殊方法一览 __repr__ 和 __str__的区别 __repr__ 返回的字符串应该准确、无歧义并且尽可能的表达出特定对象的特征,如Point(1, 2), 即包含特定属性值 __str__是在print()以及str()的时候使用 当一个类没有__str__函数时,将调用__repr__ 自定义类的布尔值 默认情况下我们自己定义的类的实例总被认为是True的,除非这个类对__bool__或者__len__函数有自己的实现 len()为什么不是一个普通方法 len()之所以不是一个普通方法是为了让python自带的数据结构可以走后门(CPython直接从一个C结构体读取对象的长度)

created: 2023-04-04  |  updated: 2023-04-04  |  阿秀

《Fluent Python》第02章 数据结构

容器序列和扁平序列 容器序列list, tuple, collections.deque这些容器内能存放不同数据类型的数据 扁平序列str, bytes, bytearray, memoryview和array.array只能存放同一数据类型 容器内容的可变与不可变 可变: list, bytearray, array.array, collections.deque, memoryview 不可变tuple, str, bytes 列表推导 列表推导(list comprehension)简称为listcomps 1 2 3 4 L = [x for x in range(100)] M = [x*y for x in range(10) for y in range(11, 20) ] print(L) print(M) 虽然老生常谈了,但是额外说一句从后往前读非常容易理解 使用原则:用列表推导来创建新的列表,并且尽量保持简短 python会忽略代码里的[], {}, ()中的换行 列表推导不一定比map()和filter()的组合速度慢 生成器表达式 生成器表达式的语法跟列表推导差不多,只不过是把方括号[]变成() 生成器逐个产生元素, 不会像列表推导一样一次性占用内存, 因此使用生成器表达式可以一定程度上节省内存 *运算符用于拆包 *运算符可以把一个可迭代对象拆开为函数的参数, 用*args来获取不确定数量的参数也是一种经典的写法...

created: 2023-04-04  |  updated: 2023-04-04  |  阿秀

《Fluent Python》第03章 字典和集合

前言 python对字典dict的实现做了高度优化,散列表是字典类型性能出众的根本原因 集合set的实现也依赖于散列表 泛映射类型 映射是一种关联式的容器类型,它存储了对象与对象之间的映射关系 collections.abc模块中有Mapping和MutableMapping这两个抽象基类, 它们的作用是为dict和其他类似的类型定义形式接口。非抽象映射类型一般不会直接继承这些抽象基类,它们会直接对dict或是collections.User.Dict进行扩展。这些基类的作用是作为形式化的文档,它们定义了构建一个映射类型所需要的最基本的接口 它们可以和isinstance()一起用于判断某个数据是不是广义上的映射类型: 1 2 3 4 from collections import abc t = dict() print(isinstance(t, abc.Mapping)) >>>True 可散列的数据类型 标准库里的所有映射类型都是利用dict实现的,因此它们有个共同的限制,即只有可散列的数据类型才能作为这些映射里的键key 如果一个对象是可以散列的,那么在这个对象的生命周期中,它的散列值是不变的,需要实现__hash__()方法以及__eq__() python里可散列的类型有str, bytes, frozenset 注意list是不可散列的 元组tuple当其包含的元素都是可散列的情况下,它才可以散列 下面这个列子: 1 2 3 4 5 6 7 8 L = [x for x in range(10)] print(hash(L)) >>>TypeError: unhashable type: 'list' # 列表[30, 40]被冻结后可以被散列 t = (1, 2, frozenset([30, 40])) print(hash(t)) >>>985328935373711578 字典的多种构造方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 a = dict(one=1, two=2, three=3) b = {'one':1, 'two':2, 'three':3} c = dict(zip(['one', 'two', 'three'], [1, 2, 3])) d = dict([('one', 1), ('two', 2), ('three', 3)]) e = dict({'three':3, 'one':1, 'two':2}) print(a) print(b) print(c) print(d) print(e) >>>{'one': 1, 'two': 2, 'three': 3} >>>{'one': 1, 'two': 2, 'three': 3} >>>{'one': 1, 'two': 2, 'three': 3} >>>{'one': 1, 'two': 2, 'three': 3} >>>{'three': 3, 'one': 1, 'two': 2} print(a==b==c==d==e) >>>True 字典推导 注意这个例子的输出…...

created: 2023-04-04  |  updated: 2023-04-04  |  阿秀

《Fluent Python》第04章 文本和字节序列

前言 python3的str对象中的元素是Unicode字符,Python3默认使用UTF-8编码源码 编码与解码 字符的标识,即码位,范围为0 ~ 1114111的数字(十进制),(可以理解为不同的数对应不同的字符),在Unicode中以4 ~ 6个十六进制数表示,而且加前缀U+。(注:1byte = 8bit = 两个十六进制数,即以2byte ~ 3byte表示一个字符,相比而言,ASCII码一个字符用1byte表示) 字符的具体表述取决于所用的编码。编码是在码位和字节序列之间转换时使用的算法(可以理解为映射方法)。在UTF-8编码中,A(U+0041)的码位编码成单个字节\x41(注:x表示十进制),而在UTF-16LE编码中编码成两个字节\x41\x00 把码位转换成字节序列的过程是编码 把字节序列转换成码位的过程是解码 1 2 3 4 5 6 7 8 9 10 11 s = 'café' print(len(s)) >>>4 b_s = s.encode('utf8') print(b_s) >>>b'caf\xc3\xa9' r = b_s.decode('utf8') print(r) >>>café 字符串café有4个Unicode字符,使用encode()方法将str对象转换为bytes对象b_s,b_s有5个字节(é) 字节概要 bytes和bytearray bytes和bytearray对象的各个元素是区间[0, 255]里的整数 1 2 3 4 5 6 7 8 9 10 11 12 13 cafe = bytes('café', encoding='utf-8') print(cafe) >>>b'caf\xc3\xa9' print(cafe[0]) >>>99 print(cafe[:1]) >>>b'c' cafe_arr = bytearray(cafe) print(cafe_arr) >>>bytearray(b'caf\xc3\xa9') print(cafe_arr[-1:]) >>>bytearray(b'\xa9') bytes对象可以从str对象使用给定的编码构建,bytearray对象可以使用bytes对象构建 bytes对象的切片仍旧是bytes对象,bytearray对象的切片仍旧是bytearray对象,s[0] == s[:1]只对str这个序列类 型成立 bytearray对象没有字面量句法,而是以bytearray()和字节序列字面量参数的形式显示 如何找出字节序列的编码 一般需要明确的标出 使用统一字符编码侦测包Chardet进行猜测 处理文本文件 Unicode三明治:要尽早把输入的字节序列(bytes)解码(decode)成字符串(str);在其他处理过程中,一定不能编码或解码;对输出来说,则要尽量晚地把字符串编码成字节序列。...

created: 2023-04-04  |  updated: 2023-04-04  |  阿秀

《Fluent Python》第05章 一等函数

一等对象 编程语言理论家把“一等对象”定义为满足下述条件的程序实体: 在运行是创建 能赋值给变量或数据结构中的元素 能作为参数传给函数 能作为函数的返回结果 把函数当作对象 函数都是function类的实例,类的方法是method类的实例(虽然经常会把方法称为函数) 1 2 3 4 5 6 7 8 9 10 11 def fun(): pass class Foo: def bar(self): pass print(type(fun)) >>><class 'function'> print(type(Foo().bar)) >>><class 'method'> 高阶函数 接受函数为参数或者把函数作为结果返回的函数称为高阶函数。 在函数式编程范式中,最为人熟知的高阶函数有map(), filter(), reduce() all()和any() all(iterable), 如果iterable的每个值都为True,返回True any(iterable), 如果iterable存在一个值为True,返回True 匿名函数 使用lambda关键字创建匿名函数,格式为lambda [arg1 [,arg2,.....argn]]:expression,匿名函数的定义体中不能赋值,不能使用while和try语句。 我十分不喜欢用匿名函数,基本没有用过,即使是用高阶函数需要传递函数作为参数时,也是额外用def语句编写函数,所以一直对lambda理解不到位。 匿名函数这样理解:将arg x作为参数传递给expression,得到结果后返回。 Lundh提出的lambda表达式重构秘笈: (1)编写注释,说明lambda表达式的作用 (2)研究注释,用一个名称来概括注释 (3)把lambda表达式改写成def,使用那个名称作为函数名 (4)删除注释 可调用对象 使用callable()函数可判断是否为可调用对象。python中有7种可调用对象: 用户使用def和lambda创建的函数 内置函数,使用C语言(CPython)实现的函数,如len或time.strftime 使用C语言实现的方法,如dict.get 方法,在类的定义体中定义的函数 类,调用类时会运行__new__方法创建一个实例,python没有new运算符,所以调用类相当于调用函数 定义了__call__()类的实例 生成器函数,使用yield关键字的函数或方法 1 2 3 L = [abs, str, 13] print([callable(x) for x in L]) >>>[True, True, False] 函数内省 函数内省(function introspection)是在运行时进行的一种对象检测机制,用来查看某个对象内部信息,如类的type类型、属性、方法、事件等等。 (内省: 文言,意思是查看内部情况。华夏特色的翻译,恕我直言,把第一个叫这个名字的人拉出去斩了)...

created: 2023-04-04  |  updated: 2023-04-04  |  阿秀