变量、运算符与数据类型
1. 注释
- 在 Python 中,
#
表示注释,作用于整行。
【例子】单行注释
1 | # 这是一个注释 |
Hello world
''' '''
或者 """ """
表示区间注释,在三引号之间的所有内容被注释
【例子】多行注释
1 | ''' |
Hello china
hello china
2. 运算符
算术运算符
操作符 | 名称 | 示例 |
---|---|---|
+ |
加 | 1 + 1 |
- |
减 | 2 - 1 |
* |
乘 | 3 * 4 |
/ |
除 | 3 / 4 |
// |
整除(地板除) | 3 // 4 |
% |
取余 | 3 % 4 |
** |
幂 | 2 ** 3 |
1 | print(1 + 1) # 2 |
2
1
12
0.75
0
3
8
比较运算符
操作符 | 名称 | 示例 |
---|---|---|
> |
大于 | 2 > 1 |
>= |
大于等于 | 2 >= 4 |
< |
小于 | 1 < 2 |
<= |
小于等于 | 5 <= 2 |
== |
等于 | 3 == 4 |
!= |
不等于 | 3 != 5 |
【例子】
1 | print(2 > 1) # True |
True
False
True
False
False
True
逻辑运算符
操作符 | 名称 | 示例 |
---|---|---|
and |
与 | (3 > 2) and (3 < 5) |
or |
或 | (1 > 3) or (9 < 2) |
not |
非 | not (2 > 1) |
【例子】
1 | print((3 > 2) and (3 < 5)) # True |
True
False
False
位运算符
操作符 | 名称 | 示例 | ||
---|---|---|---|---|
~ |
按位取反 | ~4 |
||
& |
按位与 | 4 & 5 |
||
` | ` | 按位或 | `4 | 5` |
^ |
按位异或 | 4 ^ 5 |
||
<< |
左移 | 4 << 2 |
||
>> |
右移 | 4 >> 2 |
1 | print(bin(4)) # 0b100 |
0b100
0b101
-0b101 -5
0b100 4
0b101 5
0b1 1
0b10000 16
0b1 1
三元运算符
【例子】
1 | x, y = 4, 5 |
4
有了这个三元操作符的条件表达式,你可以使用一条语句来完成以上的条件判断和赋值操作。
【例子】
1 | x, y = 4, 5 |
4
其他运算符
操作符 | 名称 | 示例 |
---|---|---|
in |
存在 | 'A' in ['A', 'B', 'C'] |
not in |
不存在 | 'h' not in ['A', 'B', 'C'] |
is |
是 | "hello" is "hello" |
is not |
不是 | "hello" is not "hello" |
【例子】
1 | letters = ['A', 'B', 'C'] |
A exists
h not exists
【例子】比较的两个变量均指向不可变类型
1 | a = "hello" |
True True
False False
【例子】比较的两个变量均指向可变类型。
注意:
- is, is not 对比的是两个变量的内存地址
- ==, != 对比的是两个变量的值
- 比较的两个变量,指向的都是地址不可变的类型(str等),那么is,is not 和 ==,!= 是完全等价的。
- 对比的两个变量,指向的是地址可变的类型(list,dict,tuple等),则两者是有区别的。
运算符的优先级
- 一元运算符优于二元运算符。例如
3 ** -2
等价于3 ** (-2)
。 - 先算术运算,后移位运算,最后位运算。例如
1 << 3 + 2 & 7
等价于1 << (3 + 2)) & 7
。 - 逻辑运算最后结合。例如
3 < 4 and 4 < 5
等价于(3 < 4) and (4 < 5)
。
【例子】
1 | print(-3 ** 2) # -9 |
-9
0.1111111111111111
0
-12.5
True
1 | teacher = "老马的程序人生" |
老马的程序人生
【例子】
1 | first = 2 |
5
1 | myTeacher = "老马的程序人生" |
老马的程序人生,小马的程序人生
3. 数据类型与转换
类型 | 名称 | 示例 |
---|---|---|
int | 整型 <class 'int'> |
-876, 10 |
float | 浮点型<class 'float'> |
3.149, 11.11 |
bool | 布尔型<class 'bool'> |
True, False |
整型
【例子】通过 print()
可看出 a
的值,以及类 (class) 是int
。
1 | a = 1031 |
1031 <class 'int'>
Python 里面万物皆对象(object),整型也不例外,只要是对象,就有相应的属性 (attributes) 和方法(methods)。
【例子】
1 | b = dir(int) |
['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
对它们有个大概印象就可以了,具体怎么用,需要哪些参数 (argument),还需要查文档。看个bit_length()
的例子。
【例子】找到一个整数的二进制表示,再返回其长度。
1 | a = 1031 |
0b10000000111
11
浮点型
【例子】
1 | print(1, type(1)) |
1 <class 'int'>
1.0 <class 'float'>
2.3e-07
2.3e-07
有时候我们想保留浮点型的小数点后 n
位。可以用 decimal
包里的 Decimal
对象和 getcontext()
方法来实现。
Python 里面有很多用途广泛的包 (package),用什么你就引进 (import) 什么。包也是对象,也可以用上面提到的dir(decimal)
来看其属性和方法。
【例子】getcontext()
显示了 Decimal
对象的默认精度值是 28 位 (prec=28
)。
1 | import decimal |
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])
0.3333333333333333333333333333
【例子】使 1/3 保留 4 位,用 getcontext().prec
来调整精度。
1 | decimal.getcontext().prec = 4 |
0.3333
布尔型
布尔 (boolean) 型变量只能取两个值,True
和 False
。当把布尔型变量用在数字运算中,用 1
和 0
代表 True
和 False
。
【例子】
1 | print(True + True) # 2 |
2
1
0
除了直接给变量赋值 True
和 False
,还可以用 bool(X)
来创建变量,其中 X
可以是
- 基本类型:整型、浮点型、布尔型
- 容器类型:字符串、元组、列表、字典和集合
【例子】bool
作用在基本类型变量:X
只要不是整型 0
、浮点型 0.0
,bool(X)
就是 True
,其余就是 False
。
1 |
|
<class 'int'> False True
<class 'float'> False True
<class 'bool'> False True
<class 'float'> True True True
【例子】bool
作用在容器类型变量:X
只要不是空的变量,bool(X)
就是 True
,其余就是 False
。
1 | print(type(''), bool(''), bool('python')) |
<class 'str'> False True
<class 'tuple'> False True
<class 'list'> False True
<class 'dict'> False True
<class 'set'> False True
确定bool(X)
的值是 True
还是 False
,就看 X
是不是空,空的话就是 False
,不空的话就是 True
。
- 对于数值变量,
0
,0.0
都可认为是空的。 - 对于容器变量,里面没元素就是空的。
获取类型信息
- 获取类型信息
type(object)
【例子】
1 | print(type(1)) # <class 'int'> |
<class 'int'>
<class 'float'>
<class 'bool'>
<class 'str'>
- 获取类型信息
isinstance(object, classinfo)
【例子】
1 | print(isinstance(1, int)) # True |
True
True
True
True
注:
type()
不会认为子类是一种父类类型,不考虑继承关系。isinstance()
会认为子类是一种父类类型,考虑继承关系。
如果要判断两个类型是否相同推荐使用 isinstance()
。
类型转换
- 转换为整型
int(x, base=10)
- 转换为字符串
str(object='')
- 转换为浮点型
float(x)
【例子】
1 | print(int('520')) # 520 |
520
520
520.52
520.0
20
15.3
4. print() 函数
print(*objects, sep=’ ‘, end=’\n’, file=sys.stdout, flush=False)
- 将对象以字符串表示的方式格式化输出到流文件对象file里。其中所有非关键字参数都按
str()
方式进行转换为字符串输出; - 关键字参数
sep
是实现分隔符,比如多个参数输出时想要输出中间的分隔字符; - 关键字参数
end
是输出结束时的字符,默认是换行符\n
; - 关键字参数
file
是定义流输出的文件,可以是标准的系统输出sys.stdout
,也可以重定义为别的文件; - 关键字参数
flush
是立即把内容输出到流文件,不作缓存。
【例子】没有参数时,每次输出后都会换行。
1 | shoplist = ['apple', 'mango', 'carrot', 'banana'] |
This is printed without 'end'and 'sep'.
apple
mango
carrot
banana
【例子】每次输出结束都用end
设置的参数&
结尾,并没有默认换行。
1 | shoplist = ['apple', 'mango', 'carrot', 'banana'] |
This is printed with 'end='&''.
apple&mango&carrot&banana&hello world
【例子】item
值与'another string'
两个值之间用sep
设置的参数&
分割。由于end
参数没有设置,因此默认是输出解释后换行,即end
参数的默认值为\n
。
1 | shoplist = ['apple', 'mango', 'carrot', 'banana'] |
This is printed with 'sep='&''.
apple&another string
mango&another string
carrot&another string
banana&another string
参考文献:
- https://www.runoob.com/python3/python3-tutorial.html
- https://www.bilibili.com/video/av4050443
- https://mp.weixin.qq.com/s/DZ589xEbOQ2QLtiq8mP1qQ
- https://www.cnblogs.com/OliverQin/p/7781019.html
练习题:
1. 怎样对python中的代码进行注释?
#
表示注释,作用于整行。''' '''
或者""" """
表示区间注释,在三引号之间的所有内容被注释
2. python有哪些运算符,这些运算符的优先级是怎样的?
算术运算符
操作符 | 名称 | 示例 |
---|---|---|
+ |
加 | 1 + 1 |
- |
减 | 2 - 1 |
* |
乘 | 3 * 4 |
/ |
除 | 3 / 4 |
// |
整除(地板除) | 3 // 4 |
% |
取余 | 3 % 4 |
** |
幂 | 2 ** 3 |
比较运算符
操作符 | 名称 | 示例 |
---|---|---|
> |
大于 | 2 > 1 |
>= |
大于等于 | 2 >= 4 |
< |
小于 | 1 < 2 |
<= |
小于等于 | 5 <= 2 |
== |
等于 | 3 == 4 |
!= |
不等于 | 3 != 5 |
逻辑运算符
操作符 | 名称 | 示例 |
---|---|---|
and |
与 | (3 > 2) and (3 < 5) |
or |
或 | (1 > 3) or (9 < 2) |
not |
非 | not (2 > 1) |
位运算符
操作符 | 名称 | 示例 | ||
---|---|---|---|---|
~ |
按位取反 | ~4 |
||
& |
按位与 | 4 & 5 |
||
` | ` | 按位或 | `4 | 5` |
^ |
按位异或 | 4 ^ 5 |
||
<< |
左移 | 4 << 2 |
||
>> |
右移 | 4 >> 2 |
其他运算符
操作符 | 名称 | 示例 |
---|---|---|
in |
存在 | 'A' in ['A', 'B', 'C'] |
not in |
不存在 | 'h' not in ['A', 'B', 'C'] |
is |
是 | "hello" is "hello" |
is not |
不是 | "hello" is not "hello" |
运算符的优先级
- 一元运算符优于二元运算符。例如
3 ** -2
等价于3 ** (-2)
。 - 先算术运算,后移位运算,最后位运算。例如
1 << 3 + 2 & 7
等价于1 << (3 + 2)) & 7
。 - 逻辑运算最后结合。例如
3 < 4 and 4 < 5
等价于(3 < 4) and (4 < 5)
。
3. python 中 is
, is not
与 ==
, !=
的区别是什么?
- is, is not 对比的是两个变量的内存地址
- ==, != 对比的是两个变量的值
- 比较的两个变量,指向的都是地址不可变的类型(str等),那么is,is not 和 ==,!= 是完全等价的。
- 对比的两个变量,指向的是地址可变的类型(list,dict,tuple等),则两者是有区别的。
4. python 中包含哪些数据类型?这些数据类型之间如何转换?
类型 | 名称 | 示例 |
---|---|---|
int | 整型 <class 'int'> |
-876, 10 |
float | 浮点型<class 'float'> |
3.149, 11.11 |
bool | 布尔型<class 'bool'> |
True, False |
类型转换
- 转换为整型
int(x, base=10)
- 转换为字符串
str(object='')
- 转换为浮点型
float(x)
位运算
1. 原码、反码和补码
二进制有三种不同的表示形式:原码、反码和补码,计算机内部使用补码来表示。
原码:就是其二进制表示(注意,有一位符号位)。
1 | 00 00 00 11 -> 3 |
反码:正数的反码就是原码,负数的反码是符号位不变,其余位取反(对应正数按位取反)。
1 | 00 00 00 11 -> 3 |
补码:正数的补码就是原码,负数的补码是反码+1。
1 | 00 00 00 11 -> 3 |
符号位:最高位为符号位,0表示正数,1表示负数。在位运算中符号位也参与运算。
2. 按位非操作 ~
1 | ~ 1 = 0 |
~
把num
的补码中的 0 和 1 全部取反(0 变为 1,1 变为 0)有符号整数的符号位在 ~
运算中同样会取反。
1 | 00 00 01 01 -> 5 |
3. 按位与操作 &
1 | 1 & 1 = 1 |
只有两个对应位都为 1 时才为 1
1 | 00 00 01 01 -> 5 |
4. 按位或操作 |
1 | 1 | 1 = 1 |
只要两个对应位中有一个 1 时就为 1
1 | 00 00 01 01 -> 5 |
5. 按位异或操作 ^
1 | 1 ^ 1 = 0 |
只有两个对应位不同时才为 1
1 | 00 00 01 01 -> 5 |
异或操作的性质:满足交换律和结合律
1 | A: 00 00 11 00 |
6. 按位左移操作 <<
num << i
将num
的二进制表示向左移动i
位所得的值。
1 | 00 00 10 11 -> 11 |
7. 按位右移操作 >>
num >> i
将num
的二进制表示向右移动i
位所得的值。
1 | 00 00 10 11 -> 11 |
8. 利用位运算实现快速计算
通过 <<
,>>
快速计算2的倍数问题。
1 | n << 1 -> 计算 n*2 |
通过 ^
快速交换两个整数。
1 | a ^= b |
通过 a & (-a)
快速获取a
的最后为 1 位置的整数。
1 | 00 00 01 01 -> 5 |
9. 利用位运算实现整数集合
一个数的二进制表示可以看作是一个集合(0 表示不在集合中,1 表示在集合中)。
比如集合 {1, 3, 4, 8}
,可以表示成 01 00 01 10 10
而对应的位运算也就可以看作是对集合进行的操作。
元素与集合的操作:
1 | a | (1<<i) -> 把 i 插入到集合中 |
集合之间的操作:
1 | a 补 -> ~a |
注意:整数在内存中是以补码的形式存在的,输出自然也是按照补码输出。
【例子】C#语言输出负数。
1 | class Program |
【例子】 Python 的bin()
输出。
1 | print(bin(3)) # 0b11 |
0b11
-0b11
0b11111111111111111111111111111101
0b11111111111111111111111111111101
4294967293
是不是很颠覆认知,我们从结果可以看出:
- Python中
bin
一个负数(十进制表示),输出的是它的原码的二进制表示加上个负号,巨坑。 - Python中的整型是补码形式存储的。
- Python中整型是不限制长度的不会超范围溢出。
所以为了获得负数(十进制表示)的补码,需要手动将其和十六进制数0xffffffff
进行按位与操作,再交给bin()
进行输出,得到的才是负数的补码表示。
练习题:
leetcode 习题 136. 只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
尝试使用位运算解决此题。
题目说明:
1 | class Solution: |