仅记录datawhale打卡学习中遇到的新知识点和过往不曾注意的知识点。
注释有两种方式。
#这是一个注释
''' 这是一个注释
啦啦啦
'''
"""
三个双引号也是多行注释
嘻嘻
"""
比较简单:
与或非
and or not
操作符 | 名称 | 示例 |
---|---|---|
~ | 按位取反 | ~4 |
& | 按位与 | 4&5 |
| |
按位或 | |
^ | 按位异或 | 4^5 |
<< | 左移 | |
>> | 右移 |
关于位运算符的说明:
摘自百度:
位操作是程序设计中对位模式按位或二进制数的一元和二元操作。
在许多古老的微处理器上, 位运算比加减运算略快, 通常位运算比乘除法运算要快很多。
在现代架构中, 情况并非如此:位运算的运算速度通常与加法运算相同(仍然快于乘法运算)。
具体用到后面再补充。
示例:
右移运算符“>>”是双目运算符。右移n位就是除以2的n次方。
参考:
位运算
三元运算符是软件编程中的一个固定格式,语法是“条件表达式?表达式1:表达式2”。
比如
x, y = 4, 5
small = x if x < y else y
print(small) # 4
可以取代条件表达式。
一元运算符有1个操作数。例如,递增运算符"++“就是一元运算符,二元运算符有2个操作数。例如,除法运算符”/"有2个操作数。
int
float
bool :True False
a = 1031
print(a, type(a))
# 1031
Python 里面万物皆对象(object),整型也不例外,只要是对象,就有相应的属性 (attributes) 和方法(methods)。
b = dir(int)
print(b)
Python 里面有很多用途广泛的包 (package),用什么你就引进 (import) 什么。包也是对象,也可以用上面提到的dir(decimal) 来看其属性和方法。
比如:
可以通过这种方法查看sklearn库中tree中的属性和方法。
保留浮点小数点后n位
#保留四位小数
import decimal
from decimal import Decimal
decimal.getcontext().prec = 4
c = Decimal(1) / Decimal(3)
print(c)
# 0.3333
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
关于python参数
关键字参数end是输出结束时的字符,默认是换行符\n,如果不做改变,则输出时每次输出后都会换行。
但加上关键字参数就不会换行了。这里我的默认结束字符是空格。
l = ["miffy","zyx","rsl","Bob"]
for i in l:
print(i,end = ' ')
其他参数说明:
示例:
l = ["miffy","zyx","rsl","Bob"]
for i in l:
print("欢迎你",i,sep=':')
答:
#用来单行注释
‘’’ ‘’'和""" “”"用来多行注释
见2(4)
参考:
python 中 is, is not ,==, != 的区别
is, is not 对比的是两个变量的内存地址
==,!= 对比的是两个变量的值
a="hello"
b="hello"
print(a is b, a==b) # 输出为 True, True
a=["hello"]
b=["hello"]
print(a is b, a==b) # 输出为 False, True
整型字符型浮点型。
先来复习一下前面学过的位运算符:
操作符 | 名称 | 示例 |
---|---|---|
~ | 按位取反 | ~4 |
& | 按位与 | 4&5 |
| |
按位或 | |
^ | 按位异或 | 4^5 |
<< | 左移 | |
>> | 右移 |
原码:
00 00 00 11 -> 3
10 00 00 11 -> -3
反码:
00 00 00 11 -> 3
11 11 11 00 -> -3
补码:
00 00 00 11 -> 3
11 11 11 01 -> -3
~代表按位置取反
~ 1 = 0
~ 0 = 1
例如二进制下00 00 01 01表示正整数5,取反
~5
输出:-6
00 00 01 01 -> 5
~
操作后:
11 11 10 10 -> -6
~-5
输出:4
11 11 10 11 -> -5
~
操作后:
00 00 01 00 -> 4
1 & 1 = 1
1 & 0 = 0
0 & 1 = 0
0 & 0 = 0
00 00 01 01 -> 5
&
00 00 01 10 -> 6
结果:
00 00 01 00 -> 4
注意:2个对应位为1结果的对应位才为1
00 00 01 01 -> 5
|
00 00 01 10 -> 6
结果:
00 00 01 11 -> 7
说明:
1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0
00 00 01 01 -> 5
^
00 00 01 10 -> 6
结果:
00 00 00 11 -> 3
注意:对应位置不同时才为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 -> 计算 n2
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
结果:(最后为1的位置是1)
00 00 00 01 -> 1
00 00 11 10 -> 14
&
11 11 00 10 -> -14
结果:(最后为1的位置是2)
00 00 00 10 -> 2
疑问:在实际中能解决什么问题?
一个数的二进制表示可以看作是一个集合(0 表示不在集合中,1 表示在集合中)。
比如集合 {1, 3, 4, 8},可以表示成 01 00 01 10 10 而对应的位运算也就可以看作是对集合进行的操作。
01 00 01 10 10
98 76 54 32 10
元素与集合的操作:
a | (1< 把 i 插入到集合中
a & ~(1< 把 i 从集合中删除
a & (1< 判断 i 是否属于该集合(零不属于,非零属于)
具体操作参考:Python之位运算实现整数集合
如原集合为 {1, 3, 4, 8},此时需要插入数字5,则运用
a | (1< 把 i 插入到集合中
a = 0b0100011010 #0b为二进制,表示集合 {1, 3, 4, 8}
b = a | (1<<5)
print(bin(b)) #输出结果:0b100111010
输出对应:集合{1,3,4,5,8}
01 00 11 10 10
98 76 54 32 10
注意:整数在内存中是以补码的形式存在的,输出自然也是按照补码输出。
举例:python的bin()输出
print(bin(3)) # 0b11
print(bin(-3)) # -0b11
print(bin(-3 & 0xffffffff))
# 0b11111111111111111111111111111101
print(bin(0xfffffffd))
# 0b11111111111111111111111111111101
print(0xfffffffd) # 4294967293
练习题:
leetcode习题 136. 只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
尝试使用位运算解决此题。
我还没想到怎么用位运算做
题目解答(用一个空字典做):
"""
Input file
example1: [2,2,1]
example2: [4,1,2,1,2]
Output file
result1: 1
result2: 4
"""
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
dic = {
}
for num in nums:
dic[num] = dic.get(num,0) + 1 #print(d.get(a,0))如果字典d里面没有指定的键值,则返回0
#通过这种方式把值不断放入字典,如果num在前面已经出现了说明value值为1,再通过get查找
#返回的就是1,再+1就是2,最终只要找那些大于1的数就行了
if dic[num] > 1: #num代表字典中的key值,
return num
#创建一个字典,记录每个数字出现的次数,每次记录后判断,次数大于1则返回该数字。