变量、运算符与数据类型
1.注释
python的注释分为单行注释和整段注释
"#“为行注释,注释内容从”#"开始知道行尾
#本行为注释
# ‘#’的作用范围为从它开始直到行尾,‘#’之前并不影响
flag='list'
a=[1,2,3] #if flag=='list' else 1; '#符号并不会影响它之前的语句'
#a=list()
‘’’ ‘’’ 或者 “”" “”" 表示区间注释,在三引号之间的所有内容被注释
#单引号注释
'''
a=[1,2,3]
b=list()
b.append(1)
'''
#双引号注释
"""
a=[1,2,3]
b=list()
b.append(1)
"""
2.运算符
算术运算符
示例:
print(2 + 2) # 4
print(1 - 5) # -4
print(3 * 4) # 12
print(3 / 4) # 0.75
print(3 // 4) # 0 整除,下取整
print(3 % 4) # 3
print(2 ** 3) # 8 幂
比较运算符
示例:
print(2 > 1) # True
print(2 >= 4) # False
print(1 < 2) # True
print(5 <= 2) # False
print(3 == 4) # False
print(3 != 5) # True
a=[1,2,3]
b=[2,3,4]
print(a>b) #False 列表也是可以比较的,默认是从列表头开始比较找到第一个不同的元素输出他们的比较结果
c='alpha'
d='beta'
print(c>d) #False 字符串比较也是从头开始比较,因为'a'的ascii码小于'b'的ascii码,故结果为False
逻辑运算符
示例:
flag=True
print(not flag) #False
print((3 > 2) and (3 < 5)) # True
print((1 > 3) or (9 < 2)) # False
print(not (2 > 1)) # False
位运算符
示例:
print(bin(4)) # 0b100
print(bin(5)) # 0b101
print(bin(~4), ~4) # -0b101 -5
print(bin(4 & 5), 4 & 5) # 0b100 4
print(bin(4 | 5), 4 | 5) # 0b101 5
print(bin(4 ^ 5), 4 ^ 5) # 0b1 1
print(bin(4 << 2), 4 << 2) # 0b10000 16
print(bin(4 >> 2), 4 >> 2) # 0b1 1
三元运算符
示例:
a=1 if 1>2 else 2
#在c++里相当于 int a=1>2?1:2;
其他运算符
【示例】:
letters = ['A', 'B', 'C']
if 'A' in letters:
print('A' + ' exists')
if 'h' not in letters:
print('h' + ' not exists')
# A exists
# h not exists
【示例】比较的两个变量均指向不可变类型。
a = "hello"
b = "hello"
print(a is b, a == b) # True True
print(a is not b, a != b) # False False
【示例】比较的两个变量均指向可变类型。
a = ["hello"]
b = ["hello"]
print(a is b, a == b) # False True
print(a is not b, a != b) # True False
注意:
is, is not 对比的是两个变量的内存地址
==, != 对比的是两个变量的值
比较的两个变量,指向的都是地址不可变的类型(str等),那么is,is not 和 ==,!= 是完全等价的。
对比的两个变量,指向的是地址可变的类型(list,dict等),则两者是有区别的。
运算符的优先级
一元运算符优于二元运算符。例如3 ** -2等价于3 ** (-2)。
先算术运算,后移位运算,最后位运算。例如 1 << 3 + 2 & 7等价于 (1 << (3 + 2)) & 7。
逻辑运算最后结合。例如3 < 4 and 4 < 5等价于(3 < 4) and (4 < 5)。
3. 变量和赋值
在使用变量之前,需要对其先赋值。
变量名可以包括字母、数字、下划线、但变量名不能以数字开头。
Python 变量名是大小写敏感的,foo != Foo。
和别的语言没啥区别,就不举例了
4. 数据类型与转换
5.print函数
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
将对象以字符串表示的方式格式化输出到流文件对象file里。其中所有非关键字参数都按str()方式进行转换为字符串输出;
关键字参数sep是实现分隔符,比如多个参数输出时想要输出中间的分隔字符;
关键字参数end是输出结束时的字符,默认是换行符\n;
关键字参数file是定义流输出的文件,可以是标准的系统输出sys.stdout,也可以重定义为别的文件;
关键字参数flush是立即把内容输出到流文件,不作缓存。
【示例】没有参数时,每次输出后都会换行。
shoplist = ['apple', 'mango', 'carrot', 'banana']
print("This is printed without 'end'and 'sep'.")
for item in shoplist:
print(item)
# This is printed without 'end'and 'sep'.
# apple
# mango
# carrot
# banana
【示例】每次输出结束都用end设置的参数&结尾,并没有默认换行。
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
【示例】item值与’another string’两个值之间用sep设置的参数&分割。由于end参数没有设置,因此默认是输出解释后换行,即end参数的默认值为\n。
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
6.位运算
原码、反码和补码
二进制有三种不同的表示形式:原码、反码和补码,计算机内部使用补码来表示。
原码:就是其二进制表示(注意,最高位是符号位)。
#最高位为符号位,0表示正号,1表示负号
0000 1001 -> 9
1000 1001 -> -9
反码:正数的反码就是原码,负数的反码是符号位不变,其余位取反(对应正数按位取反)。
#最高位为符号位,0表示正号,1表示负号
0000 1001 -> 9
1111 0110 -> -9
补码:正数的补码就是原码,负数的补码是反码+1。
#最高位为符号位,0表示正号,1表示负号
0000 1001 -> 9
1111 0111 -> -9
按位非操作 ~
~ 把num的补码中的 0 和 1 全部取反(0 变为 1,1 变为 0)有符号整数的符号位在 ~ 运算中同样会取反。
a=7 #二进制 0000 0111
print(~a) #-8 按位取反 1111 1000(补码表示) 将1111 1000转换成原码即 补码减一取反码即 1000 1000结果为-8
按位与操作 &
只有两个对应位都为 1 时才为 1
a=8 #0000 1000
b=7 #0000 0111
print(a&b) #0
按位或操作 |
只要两个对应位中有一个 1 时就为 1
a=8 #0000 1000
b=7 #0000 0111
print(a|b) #15 0000 1111
按位异或操作 ^
只有两个对应位不同时才为 1
异或其实可以看成不进位加法,在一些算法题中经常会用到
a=8 #0000 1000
b=9 #0000 1001
print(a^b) #1 0000 0001
左移和右移
num << i 将num的二进制表示向左移动i位所得的值。
num >> i 将num的二进制表示向右移动i位所得的值。
左移一位可以看做num*2
右移一位可以看做num//2
所以在做二分问题求mid的时候可以写为(left+right)>>1
#左移
00 00 10 11 -> 11
11 << 3
---
01 01 10 00 -> 88
#右移
00 00 10 11 -> 11
11 >> 2
---
00 00 00 10 -> 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 & (-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
python负数的二进制表示
bin()可以输出二进制表示
print(bin(3)) # 0b11
print(bin(-3)) # -0b11
print(bin(-3 & 0xffffffff))
# 0b11111111111111111111111111111101
print(bin(0xfffffffd))
# 0b11111111111111111111111111111101
print(0xfffffffd) # 4294967293
Python中bin一个负数(十进制表示),输出的是它的原码的二进制表示加上个负号,巨坑。
Python中的整型是补码形式存储的。
Python中整型是不限制长度的不会超范围溢出。
所以为了获得负数(十进制表示)的补码,需要手动将其和十六进制数0xffffffff进行按位与操作,再交给bin()进行输出,得到的才是负数的补码表示。
位运算练习题 leetcode 136 只出现一次的数字
题目:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
思路:因为数组中只有一个元素出现一次,其余所有元素均出现两次,故可以考虑异或操作,相同数字异或结果为0,0异或任何数都不改变那个数,所以对数组中所有元素依次做异或,相同元素异或得0,0异或0为0,最后只剩下只出现一次的元素,即为所求。
代码:
class Solution:
def singleNumber(self, nums: List[int]) -> int:
res=0;
for num in nums:
res^=num
return res
参考
https://github.com/datawhalechina/team-learning-program/tree/master/Python-Language