表示注释:
#
作用于整行''' '''
或者 """ """
表示区间注释比较运算符:
!=
表示不等于逻辑运算符:
and
与
or
或
not
非
位运算符
操作符 | 名称 | 示例 |
---|---|---|
~ |
按位取反 | ~4 |
& |
按位与 | 4 & 5 |
` | ` | 按位或 |
^ |
按位异或 | 4 ^ 5 |
<< |
左移 | 4 << 2 |
>> |
右移 | 4 >> 2 |
三元运算符
例子
x, y = 4, 5
small = x if x < y else y
print(small) # 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" |
__注意__
is
,is not
对比的是两个变量的内存地址==
,!=
对比的是两个变量的值- 比较的两个变量,指向的都是地址不可变的类型(str等),那么
is
,is not
和==
,!=
是完全等价的。- 对比的两个变量,指向的是地址可变的类型(list,dict,tuple等),则两者是有区别的。
例子
【例子】比较的两个变量均指向可变类型。
a = ["hello"]
b = ["hello"]
print(a is b, a == b) # False Tru
print(a is not b, a != b) # True False
类型 | 名称 | 示例 |
---|---|---|
int |
整型
|
-876, 10 |
float |
浮点型
|
3.149, 11.11 |
bool |
布尔型
|
True, False |
获取类型信息:用type(object)
类型转换
int(x, base=10)
str(object='')
float(x)
保留浮点型小数点后n位
import decimal
from decimal import Decimal
decimal.getcontext().prec = 4
c = Decimal(1) / Decimal(3)
print(c)
bool作用在基本类型的变量
bool作用在容器类型变量
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
关键字参数:sep、end、file、flush
sep作用: 实现分隔符,比如多个参数输出时想要输出中间的分割字符。
shoplist = ['apple', 'mango', 'carrot', 'banana']
print("This is printed with 'sep='&''.")
for item in shoplist:
print(item, 'another string', sep='&')
# 输出结果
This is printed with 'sep='&''.
apple&another string
mango&another string
carrot&another string
banana&another string
此时
end
参数默认是\n
,即输出后换行。
end作用: 默认是换行符\n
,用于输出结束时的字符。
shoplist = ['apple', 'mango', 'carrot', 'banana']
print("This is printed with 'end='&''.")
for item in shoplist:
print(item, end='&')
print('hello world')
# 输出结果
This is printed with 'end='&''.
apple&mango&carrot&banana&hello world
二进制有三种表现形式。计算机内部使用补码来表示。
原码:有一位符号位。
反码:正数的反码就是其原码,负数的反码是符号位不变,其余位取反。
补码:正数的补码就是其原码,负数的补码是反码+1。
符号位:最高位是符号位,0表示正数,1表示负数。
按位异或操作 ^
1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0
只有两个对应位不同时才为1。
按位左移 <<
num << i
将num
的二进制表示向左移动i
位所得的值。
00 00 10 11 -> 11
11 << 3
---
01 01 10 00 -> 88
按位右移 >>
num >> i
将num
的二进制表示向右移动i
位所得的值。
00 00 10 11 -> 11
11 >> 2
---
00 00 00 10 -> 2
通过 <<
,>>
快速计算2的倍数问题。
n << 1 -> 计算 n*2
n >> 1 -> 计算 n/2,负奇数的运算不可用
n << m -> 计算 n*(2^m),即乘以 2 的 m 次方
n >> m -> 计算 n/(2^m),即除以 2 的 m 次方
1 << n -> 2^n
通过 ^
快速交换两个整数。 通过 ^
快速交换两个整数。
a ^= b
b ^= a
a ^= b
通过 a & (-a)
快速获取a
的最后为 1 位置的整数。
#例子1
00 00 01 01 -> 5
&
11 11 10 11 -> -5
---
00 00 00 01 -> 1
#例子2
00 00 11 10 -> 14
&
11 11 00 10 -> -14
---
00 00 00 10 -> 2
一个数的二进制表示可以看作是一个集合(0表示不在此集合中,1表示在此集合中)。以集合 {1,3,4,8}
为例,可以表示成 01 00 01 10 10
。
整数 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|
二进制位 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 0 |
从表格中我们可以直观地看到,哪个整数在集合中,那么该数字对应的二进制位的值就是1,反之哪个整数不在该集合中,则二进制位的值取0。
以上述例子继续讨论,当我们想在原集合中 插入 一个2,那么代码实现是:
a = 0b0100011010
b = a | (1<<2) #把2插入到集合中
print(bin(b)) #0b100011110
插入数字2就是将二进制对应序号为2的位置的值置为1,表示该集合中有一个值为2的整数。
接下来,假设我们把上述集合中的元素4从集合中 删除 ,可以用代码实现:
c = b & ~(1<<4) #把4从集合中删除
print(bin(c)) #0b0100001110
假定集合b{1,2,3,4,8},判断3,5是否在集合中,可以用代码实现:
b & (1<<3) #8 (非零属于)
b & (1<<5) #0 (零不属于)
根据位数的多少来定义一个全集,比如说是16位表示一个集合 {0,1,2,...,14,15}
,那么其补集、任意两元素大小在0-15之间的集合的交集、并集、差集都可以用位运算的方式进行计算。以集合 a{1,5,6,8}
,b{1,2,5,6,8}
为例。
a的补集
a = 0b0101100010
a_com = bin(~a & 0xffff)
print(a_com)
#0b1111111010011101
a的补集对应为{0,2,3,4,7,9,10,11,12,13,14,15}
a和b的交集
a = 0b0101100010
a_b = a & b #a交b
print(bin(a_b))
# 0b101100010
交集对应的集合{1,5,6,8}
a与b的并集
a = 0b0101100010
ab = a | b #a并b
print(bin(ab))
# 0b101100110
对应的集合是{1,2,5,6,8}
b与a的差集
a = 0b0101100010
b_a = b & (~a) #a差b
print(bin(b_a))
# 0b100
以上二进制码输出均为补码输出
首先我们来看C#语言中输出负数的例子。
class Program
{
static void Main(string[] args)
{
string s1 = Convert.ToString(-3, 2);
Console.WriteLine(s1);
// 11111111111111111111111111111101
string s2 = Convert.ToString(-3, 16);
Console.WriteLine(s2);
// fffffffd
}
}
我们发现对于数字-3
的二进制码,是以补码的形式输出。
那么在python中,结果是不一样的。
print(bin(3)) # 0b11
print(bin(-3)) # -0b11
并不是以补码的形式输出,而是在原码的二进制表示前加上负号, 巨坑 ,因此若要以补码形式输出,就要进行转换,手动将其和十六进制数 0xffffffff
进行按位与操作,再交给 bin()
进行输出,得到的才是负数的补码。
print(bin(-3 & 0xffffffff)) #按位与操作
# 0b11111111111111111111111111111101
print(bin(0xfffffffd))
# 0b11111111111111111111111111111101
print(0xfffffffd) # 4294967293
# 测试整型长度,是否会溢出
print(bin(1213554555544897444444445555666787))
#0b11101111010101001101100100000010011111010001001110110110110011100001011100000001001000001000011010111101100011
总结
- Python中
bin
一个负数(十进制表示),输出的是它的原码的二进制表示再加上个负号,巨坑!- Python中的整型是以补码形式存储的。
- Python中整型是不限制长度的,不会超范围溢出。