秃头的一天

Posted 15184742286lh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了秃头的一天相关的知识,希望对你有一定的参考价值。

  1. 以下假设变量 a 为 10, b为 20: and x and y 布尔"与" - 如果 x 为 False,x and y 返回 False,否则它返回 y 的计算值。 (a and b) 返回 20。

    百度之后得到结论:

    python 中的 and 从左到右计算表达式,若所有值均为真,则返回最后一个值,若存在假,返回第一个假值;

    or 也是从左到有计算表达式,返回第一个为真的值;

    其中数字 0 是假,其他都是真;

    字符 "" 是假,其他都是真;

  2. 一开始输入了

    a = 00111100

    这么个赋值语句被提示了错误,于是去搜了下相关的博客得知 python 中数字有以下的表示方式:

    2 进制是以 0b 开头的: 例如: 0b11 则表示十进制的 3

    8 进制是以 0o 开头的: 例如: 0o11 则表示十进制的 9

    16 进制是以 0x 开头的: 例如: 0x11 则表示十进制的 17

    但是在测试的时候又遇到了个问题,那就是输出来的被自动转化成了十进制:

    >>> a=0b111100
    >>> a
    60

    于是又去找了怎么输出二进制,得到了以下内容:

    分别使用 bin,oct,hex 可输出数字的二进制,八进制,十六进制形式,例如:

    >>> a=0b111100
    >>> a=60
    >>> bin(a)
    ‘0b111100‘
    >>> oct(a)
    ‘0o74‘
    >>> hex(a)
    ‘0x3c‘

    疑问解决!

  3. 刚开始学 python,当想要自增运算的时候很自然的 a++,结果发现编译器是不认识 ++ 的,于是去网上搜了一下,结果发现一篇老外的问答很精彩,涉及到了 python 这个语言的设计原理。

    问题无外乎就是 python 没有自增运算符,自增操作是如何实现的。

    回答中有人介绍了关于自增操作,python 不使用 ++ 的哲学逻辑:编译解析上的简洁与语言本身的简洁,就不具体翻译了。

    后面还有老外回答并附带了一个例子非常的精彩,指出了 python 与 c 语言概念上的一些差异,语言描述的可能未必准确,直接上例子:

    >>> b = 5  
    >>> a = 5  
    >>> id(a)  
    162334512  
    >>> id(b)  
    162334512  
    >>> a is b  
    True

    可以看出, python 中,变量是以内容为基准而不是像 c 中以变量名为基准,所以只要你的数字内容是5,不管你起什么名字,这个变量的 ID 是相同的,同时也就说明了 python 中一个变量可以以多个名称访问。

    这样的设计逻辑决定了 python 中数字类型的值是不可变的,因为如果如上例,a 和 b 都是 5,当你改变了 a 时,b 也会跟着变,这当然不是我们希望的。

    因此,正确的自增操作应该 a = a + 1 或者 a += 1,当此 a 自增后,通过 id() 观察可知,id 值变化了,即 a 已经是新值的名称。

  4. 纠正一下楼上的一些观点

    楼上的同学所说的在脚本式编程环境中没有问题。但是在交互式环境中,编译器会有一个小整数池的概念,会把(-5,256)间的数预先创建好,而当a和b超过这个范围的时候,两个变量就会指向不同的对象了,因此地址也会不一样,比如下例:

    >>> a=1000
    >>> b=1000
    >>> id(a);id(b)
    2236612366224
    2236617350384
    >>>
  5. 位运算,是自己平时最不熟悉的一块,相信很多人也是这样,但巧妙的运用位运算可以来解决很多题目,例如,剑指offer上面的一道:

    输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

    # -*- coding:utf-8 -*-
    
    class Solution:
        def NumberOf1(self, n):
            # write code here
            cnt = 0
            if n<0:
                n = n & 0xffffffff
            while n:
                cnt+=1
                n = (n-1) & n
            return cnt

    通过按位与,巧妙的计算出二进制中"1"的个数。

  6. is 和 ==

    is 判断两个变量是否是引用同一个内存地址。

    == 判断两个变量是否相等。

    如果不用 a = b 赋值,int 型时,在数值为 -5~256(64位系统)时,两个变量引用的是同一个内存地址,其他的数值就不是同一个内存地址了。

    也就是,a b 在 -5~256(64位系统)时:

    a = 100
    b = 100
    a is b # 返回 True

    其他类型如列表、元祖、字典让 a、b 分别赋值一样的时:

    a is b  # 返回False
  7. == 和 is 的区别

    is 判断两个对象是否为同一对象, 是通过 id 来判断的; 当两个基本类型数据(或元组)内容相同时, id 会相同, 但并不代表 a 会随 b 的改变而改变。

    == 判断两个对象的内容是否相同, 是通过调用 __eq__() 来判断的。

    1、当列表,元组,字典中的值都引用 a,b 时,总是返回 True,不受 a,b 值大小的影响

    a=1000
    b=1000
    list1=[a,3,5]
    list2=[b,4,5]
    print(list1[0] is list2[0])
    tuple1=(a,3,5)
    tuple2=(b,4,5)
    print(tuple1[0] is tuple2[0])
    dict1={6:a,2:3,3:5}
    dict2={1:b,2:4,3:7}
    print(dict1[6] is dict2[1])

    输出结果为:

    True
    True
    True

    2、当不引用a,b,直接用具体值来测试时,列表,字典,不受值大小影响,返回True,元组则受 256 值范围的影响,超出范围则地址改变,返回 False。

    list1=[1000,3,5]
    list2=[1000,4,5]
    print(list1[0] is list2[0])
    tuple1=(1000,3,5)
    tuple2=(1000,4,5)
    print(tuple1[0] is tuple2[0])
    dict1={6:1000,2:3,3:5}
    dict2={1:1000,2:4,3:7}
    print(dict1[6] is dict2[1])

    输出结果为:

    True
    False
    True

    3、当直接用列表、元组、字典本身来测试时,刚好相反,元组返回 True,列表,字典返回 False。

    list1=[1000,3,5]
    list2=[1000,3,5]
    print(list1 is list2)
    tuple1=(1000,3,5)
    tuple2=(1000,3,5)
    print(tuple1 is tuple2)
    dict1={1:1000,2:3,3:5}
    dict2={1:1000,2:3,3:5}
    print(dict1 is dict2)

    输出结果为:

    False
    True
    False
  8. 关于 is 和 == 的标识问题

    (1)只要是变量的值相同,标识都相同,没有-5~256的限制,看下面的例子:

    a = 100000
    b = 100000
    if a is b:
        print(‘a 和 b 标识相同,标识为:‘,id(a))
    else:
        print(‘a 和 b 标识不相同,a 标识为:‘,id(a),‘b 标识为:‘,id(b))

    输出结果为:

    a  b 标识相同,标识为: 2158477874512

    (2)同样的如果是负数,仍然没有上述限制:

    a = -100000
    b = -100000
    if a is b:
        print(‘a 和 b 标识相同,标识为:‘,id(a))
    else:
        print(‘a 和 b 标识不相同,a 标识为:‘,id(a),‘b 标识为:‘,id(b))

    输出结果为:

    a  b 标识相同,标识为: 2137845175632

    (3)列表也是一样的,只要是列表项数值一样,那么标识也是一样的。例子如下:

    list1 = [10000,20000,30000]
    list2 = [10000,12000,15000]
    if list1[0] is list2[0]:
        print(‘list1[0] 和 list2[0] 标识相同,标识为:‘,id(list1[0]))
    else:
        print(‘list1[0] 和 list2[0] 标识不相同,list1[0]标识为:‘,id(list1[0]),‘list2[0]标识为:‘,id(list2[0]))

    输出结果为:

    list1[0]  list2[0] 标识相同,标识为: 1375086286224

    (4)元组的标识是跟着变量名的,变量名不一样,标识也不一样,上例子:

    tuple1 = (10000,20000,30000)
    tuple2 = (10000,12000,15000)
    if tuple1[0] is tuple2[0]:
        print(‘tuple1[0] 和 tuple2[0] 标识相同,标识为:‘,id(tuple1[0]))
    else:
        print(‘tuple1[0] 和 tuple2[0] 标识不相同,tuple1[0] 标识为:‘,id(tuple1[0]),‘tuple2[0]标识为:‘,id(tuple2[0]))

    输出结果为:

    tuple1[0]  tuple2[0] 标识不相同,tuple1[0] 标识为: 1375086286384 tuple2[0]标识为: 1375086286480

    (5)字典和列表是一样的,只要是列表项数值一样,那么标识也是一样的。例子如下:

    dict1 = {1:10000,2:20000,3:30000}
    dict2 = {1:10000,2:12000,3:15000}
    if dict1[1] is tuple2[1]:
        print(‘dict1[1] 和 tuple2[1] 标识相同,标识为:‘,id(dict1[1]))
    else:
        print(‘dict1[1] 和 tuple2[1] 标识不相同,dict1[1] 标识为:‘,id(dict1[1]),‘tuple2[1] 标识为:‘,id(dict2[1]))

    输出结果为:

    dict1[1]  tuple2[1] 标识不相同,dict1[1] 标识为: 1375086286224 tuple2[1] 标识为: 1375086286224
  9. 深刻理解 and、or 逻辑运算符:

    print(0 and 1)      # =>0,0等同于False
    print(False and 1)  # =>False
    print(-1 and 1)     # =>1
    print(1 or False)   # =>1,非零等同于True
    print(True or False)# =>True
    print(-1 or 0)      # =>-1
    • and:前面为假(0 或者 False)则表达式为假,否则表达式为后面的值;
    • or:前面为真(非 0 或者非 False)则表达式为前面的值,否则表达式为后面的值;

    优先级:not>and>or

    print(1 and 0 or  not False) #=>True
    print( not False or 1 and 0) #=>True
    print( 1 or not True and 0)  #=>1
  10. 看了 "is" 和 "==" 的区别,我有了进一步的了解。

    is 是比较对象是否相同(is 表示对象标识符即 object identity),即用 id() 函数查看的地址是否相同,如果相同则返回 True,如果不同则返回 False。is 不能被重载。

    == 是比较两个对象的值是否相等,此操作符内部调用的是 __eq__() 方法。所以 a==b 等效于a.__eq__(b),所以 = 可以被重载。

  11. and or not

    优先级:

    () > not > and > or

    1.or

    在 Python 中,逻辑运算符 or,x or y, 如果 x 为 True 则返回 x,如果 x 为 False 返回 y 值。因为如果 x 为 True 那么 or 运算就不需要在运算了,因为一个为真则为真,所以返回 x 的值。如果 x 的值为假,那么 or 运算的结果取决于 y,所以返回 y 的值。

    print(1 or 2)   # 1
    print(3 or 2)   # 3
    print(0 or 2)   # 2
    print(0 or 100) # 100
    print(0 or 0)

    2.and

    在 Python 中,逻辑运算符 and,x and y,如果 x 为 True 则返回 y 值。如果 x 为 False 则返回 x 值。如果 x 的值为 True,and 的运算不会结束,会继续看 y 的值,所以此时真与假取决于 y 的值,所以 x 如果为真,则返回 y 的值。如果 x 为假,那么 and 运算就会结束运算过程了,因为有一个为假则 and 为假,所以返回 x 的值。

    print(1 and 2)  # 2
    print(3 and 0)  # 0
    print(0 and 2)  # 0
    print(3 and 2)  # 2
    print(0 and 0)  # 0

    3.混合例子与解析

    按照从左向由,优先级高的先执行优先级高的规则,首先因为比较运算符优先级高于逻辑运算符,很简单,如果运算符低于了逻辑运算符优先级那还如何运算呢。and 优先级大于 or,not 优先级大于 and 和 or。

    not 4 > 5 为 True

    1 > 2 为 False

    3 < 2 为 False

    Flase and 3 为 False,因为False为假所以and不在运算直接返回False

    4 and False 为 False,因为 4 为真所以 and 运算符会继续运算后面的,以 False 为主,所以返回 False。

    False or False 为 False

    False or True 为 True

    False or False 为 False,因为 False 为假,所以 or 运算符会继续运算后面的,以 False 为主,所以返回后面的 False 值

  12. 剑指offer上面的一道:

    # -*- coding:utf-8 -*-
    class Solution:
        # bin函数: bin返回一个整数的二进制字符串,以0b开头,
        # bin(10) ‘0b1010‘  bin(-10)  ‘-0b1010‘
        #
        # count函数 返回字符串当中非重叠的字符串的个数,可以传入start,end来表示对字符串切片的结果
        #
        #如果一个数为负数,那么2**32 + n 然后再用bin返回的就是它的补码形式。 补码+源码=2**32
        def NumberOf1(self, n):
            if n >= 0:
                return bin(n).count(‘1‘)
            else:
                return bin(2**32 + n).count(‘1‘)
     
    if __name__ == ‘__main__‘:
        solution = Solution()
        print(solution.NumberOf1(10))
        print(solution.NumberOf1(-10))
  13. 除了使用python内置的bin函数和字符串计数方法count求二进制数据的1的个数外,用自己的表达式求解可如下做:

    a = 60 #其二进制值为0b00111100
    n = 0 #用于计数
    while a: #用移位方法求解,直到a移位为0为止
        if a & 1 == 1:
            n += 1 #将a与1进行位与操作,即可知道a的最后1位是否为1,若为1,则计数n增1,不然则无需变化n的值
        a >>= 1 #测试了a的最后一位后,将最后一位右移移除,重新赋值给a
    print(n) #打印最后的计数数据

    以上代码显示n=4,计算正确。

以上是关于秃头的一天的主要内容,如果未能解决你的问题,请参考以下文章

onBackPressed 上的 Android 片段 NullPointerException

一日一技:如何从多个Jupyter Notebook中找到需要代码段

除了敲代码,程序员的一天日常是怎么样的?

寒假每一天

一位高级数据科学家典型的一天:从结对编程敏捷开发,到编写代码

我与git“美妙”的一天