【Python基础入门】01 从变量到异常处理

本文详细介绍了Python的基础知识,包括变量、运算符(如比较、逻辑、位运算)、数据类型转换,以及位运算在整数集合操作中的应用。重点讲解了位运算符的使用,如按位与、或、异或、左移和右移,并展示了如何利用位运算快速计算、交换数值以及实现整数集合的操作。此外,还探讨了Python中二进制表示的特殊性,指出Python中负数的二进制表示并非补码形式。

1. 变量、运算符与数据类型

表示注释:

  • # 作用于整行
  • ''' ''' 或者 """ """ 表示区间注释

运算符

比较运算符:

  • != 表示不等于

逻辑运算符:

  • 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等),那么isis 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整型 <class 'int'>-876, 10
float浮点型<class 'float'>3.149, 11.11
bool布尔型<class '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作用在基本类型的变量

  • 只要X不是整型0、浮点型0.0,那么bool(X)就是True,其余就是False。

bool作用在容器类型变量

  • 只要X不是空变量,bool(X)就是True,其余就是False。

print()函数

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

2. 位运算

原码、反码和补码

二进制有三种表现形式。计算机内部使用补码来表示。

原码:有一位符号位。

反码:正数的反码就是其原码,负数的反码是符号位不变,其余位取反。

补码:正数的补码就是其原码,负数的补码是反码+1。

符号位:最高位是符号位,0表示正数,1表示负数。

按位运算

按位异或操作 ^

1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0

只有两个对应位不同时才为1。

按位左移 <<

num << inum的二进制表示向左移动i位所得的值。

00 00 10 11 -> 11
11 << 3
---
01 01 10 00 -> 88 

按位右移 >>

num >> inum的二进制表示向右移动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

整数9876543210
二进制位0100011010

从表格中我们可以直观地看到,哪个整数在集合中,那么该数字对应的二进制位的值就是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

💡 以上二进制码输出均为补码输出

Python中二进制码输出的特殊点

首先我们来看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中整型是不限制长度的,不会超范围溢出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值