Task 1:变量、运算符、数据类型及位运算(Datawhale-Python学习笔记)

1.1 变量、运算符与数据类型

1.1.1 注释

1.在Python中,#表示注释,作用于整行(不同行将失效)。
2.''' '''""" """表示区间注释,在三引号之间的不同行内容都可以被注释。

1.1.2 运算符

Python中的运算符可以分为6类:算术运算符、比较运算符、逻辑运算符、位运算符、三元运算符、其他运算符。

1.1.2.1 算术运算符

操作符名称示例
+1+1 == 2
-2-1 == 1
*3*4 == 12
/3/4 == 0.75
//整除(向下取整)3//4 == 0
%取余3%4 == 3
**取幂2**3 == 8

1.1.2.2 比较运算符

操作符名称示例
>大于2>1
>=大于等于2>=(2 or 1)
<小于1<2
<=小于等于2<=(2 or 5)
==等于3==3
!=不等于3!=5

1.1.2.3 逻辑运算符

操作符名称示例
and(2>1) and (3>7) == False
or(1>3) or (2<9) == True
notnot(2>1) == False

1.1.2.4 位运算符

操作符名称示例
~按位取反~0100 == 1011
&按位与0100 & 1111 == 0100
|按位或0100 | 1111 == 1111
^按位异或0100 ^ 1111 == 1011
<<左移4<<2表示整数4按位左移2位
>>右移4>>2表示整数4按位右移2位

位运算符的具体内容见1.2节。

1.1.2.5 三元运算符

有了三元操作符的条件表达式,你可以使用一条语句来完成以下的条件判断和赋值操作。

x, y = 4, 5
if x < y:
	small = x
else:
	small = y

#结果
4

1.1.2.6 其他运算符

操作符名称示例
in存在'A' in ['A', 'B', 'C'] == True
not in不存在'h' not in ['A', 'B', 'C'] == True
is"hello" is "hello" == True
is not不是"hello" is not "hello" == False

注意!!!

  • is, is not对比的是两个变量的内存地址
  • ==, !=对比的是两个变量的值
  • 比较的两个变量,指向的都是地址不可变的类型(str等),那么is, is not==, != 是完全等价的。
  • 对比的两个变量,指向的是地址可变的类型(list,dict,tuple等),则两者是有区别的:内存地址不同。

1.1.2.7 运算符的优先级

  • 一元运算符优于二元运算符。(一元运算的操作对象只有1个,二元运算的操作对象只有2个)
  • 算术运算 > 移位运算 > 位运算 > 逻辑运算。

1.1.3 变量和赋值

  • 变量名可以包括字母、数字、下划线,但变量名不能以数字开头。
  • Python 变量名是大小写敏感的,foo 不等于 Foo
  • 字符或字符串可以直接相加,组成更长的字符串。

1.1.4 数据类型与转换

类型名称示例
int整型<class 'int'>-876, 10
float浮点型<class 'float'>3.1415, -11.1
bool布尔型<class 'bool'>True, False

Python里面万物皆对象object,也包括整型。所有对象都拥有相应的属性attributes和方法method
dit()函数可以查看某一对象的方法的目录。help()函数可以查看某一对象的属性和方法的详细介绍。

  • 浮点数tip:decimal函数库里的Decimal对象和getcontext()方法来控制需要保留的小数点位。prec默认为28。例如:
decimal.getcontext().prec = 4
c = Decimal(1) / Decimal(3)
print(c)

# 0.3333
  • 布尔型tip:确定bool(X)的值,要看 X是不是空,空的话就是False,不空的话就是True

type()函数可以查看一个变量的数据类型。
isinstance(object, classinfo)判断对象object是否是一个已知的类型classinfo(例如int,float,str等)。

  • type()不会认为子类是一种父类类型,不考虑继承关系。
  • isinstance()会认为子类是一种父类类型,考虑继承关系。
  • 如果判断两个类型是否相同,推荐使用isinstance()

类型转换

  • 转换为整型int(x, base = 10)
  • 转换为字符串str(object = ' ')
  • 转换为浮点型float(x)

1.1.5 print()函数

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
  • 将对象以字符串表示的方式格式化输出到流文件对象file里。其中所有非关键字参数都按str()方式进行转换为字符串输出;
  • 关键字参数sep是实现分隔符,比如多个参数输出时想要输出中间的分隔字符;
  • 关键字参数end是输出结束时的字符,默认是换行符\n
  • 关键字参数file是定义流输出的文件,可以是标准的系统输出sys.stdout,也可以重定义为别的文件;
  • 关键字参数flush是立即把内容输出到流文件,不作缓存。

1.2 位运算

1.2.1 原码、反码和补码

二进制有三种不同的表示形式:原码、反码和补码,计算机内部使用补码来表示。
原码:就是其二进制表示(注意,最高位是符号位)。

00 00 00 11 -> 3
10 00 00 11 -> -3

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

00 00 00 11 -> 3
11 11 11 00 -> -3

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

00 00 00 11 -> 3
11 11 11 01 -> -3

1.2.2 按位非操作~

~ 把num的补码中的 0 和 1 全部取反(0 变为 1,1 变为 0)有符号整数的符号位在~运算中同样会取反。

00 00 01 01 -> 5
~
11 11 10 10 -> -6
#################
11 11 10 11 -> -5
~
00 00 01 00 -> 4

1.2.3 按位与操作&

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

00 00 01 01 -> 5
&
00 00 01 10 -> 6
----------------
00 00 01 00 -> 4

1.2.4 按位或操作|

只要两个对应位中有一个 1 时就为 1。

00 00 01 01 -> 5
|
00 00 01 10 -> 6
----------------
00 00 01 11 -> 7

1.2.5 按位异或操作^

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

00 00 01 01 -> 5
^
00 00 01 10 -> 6
----------------
00 00 00 11 -> 3

1.2.6 按位左移操作 <<

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

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

1.2.7 按位右移操作 >>

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

00 00 10 11 -> 11
11 >> 2
-----------------
00 00 00 10 -> 2

1.2.8 利用位运算实现快速计算

  • 通过<<>>快速计算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 位置的整数。
00 00 01 01 -> 5
&
11 11 10 11 -> -5
-----------------
00 00 00 01 -> 1
##################
00 00 11 10 -> 14
&
11 11 00 10 -> -14
------------------
00 00 00 10 -> 2

1.2.9 利用位运算实现整数集合

一个数的二进制表示可以看作是一个集合(0 表示不在集合中,1 表示在集合中)。

比如集合{1, 3, 4, 8},可以表示成01 00 01 10 10而对应的位运算也就可以看作是对集合进行的操作。下表更详细表示:

9876543210
0100011010
8431
  • 元素与集合的操作:
a | (1<<i)  -> 把 i 插入到集合中
a & ~(1<<i) -> 把 i 从集合中删除
a & (1<<i)  -> 判断 i 是否属于该集合(零不属于,非零属于)
  • 集合之间的操作:
a 补   -> ~a
a 交 b -> a & b
a 并 b -> a | b
a 差 b -> a & (~b)
  • Python中bin一个负数(十进制表示),输出的是它的原码的二进制表示加上个负号,巨坑。
  • Python中整型在内存中是以补码的形式存在的,输出自然也是按照补码输出。
  • Python中整型是不限制长度的不会超范围溢出。

所以为了获得负数(十进制表示)的补码,需要手动将其和十六进制数0xffffffff进行按位与操作,再交给bin()进行输出,得到的才是负数的补码表示。


练习题:
leetcode 习题 136. 只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
尝试使用位运算解决此题。

"""
Input file
example1: [2,2,1]
example2: [4,1,2,1,2]

Output file
result1: 1
result2: 4
"""

class Solution:
    def singleNumber(self, nums: List[int]) -> int:
		n0 = nums[0]
        for num in nums[1:]:
            n0 = n0 ^ num
        return n0
     # your code here

异或操作有交换律定理,相当于将相同的数字先异或,两两异或就只剩0了,然后0再和最后的一个数字异或得到最终值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值