我最近在某处读过Nonepython 中的特殊值是它自己类的单例对象,具体来说NoneType.这解释了很多,因为涉及Nonepython的大多数错误产生AttributeErrors而不是某些特殊的"NoneError"或其他东西.
由于所有的这些AttributeErrors反映了属性的NoneType缺乏,我开始用什么属性感兴趣NoneType 并如有有.
我决定研究这个NoneType并了解更多相关信息.我总是发现学习新语言功能的最佳方法是使用它,所以我尝试NoneType在IDLE中实例化:
>>> n = NoneType()
Run Code Online (Sandbox Code Playgroud)
这产生了一个错误:
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
n = NoneType()
NameError: name 'NoneType' is not defined
Run Code Online (Sandbox Code Playgroud)
困惑,我检查None了我是否得到了正确的类型名称.果然,
>>> type(None)
<class 'NoneType'>
Run Code Online (Sandbox Code Playgroud)
现在非常困惑,我做了一个快速的谷歌搜索.这表明由于某些原因,在Python 3中以某种方式删除了NoneType.
好吧,不过,哈哈!我可以通过None在变量中存储类型来解决这个问题,因为类是python中的对象.这似乎有效:
>>> NoneType = type(None)
>>> n = NoneType()
Run Code Online (Sandbox Code Playgroud)
当我打印n时,我得到的是我所期待的:
>>> print(n)
None
Run Code Online (Sandbox Code Playgroud)
但后来发生这种情况:
>>> n is None …Run Code Online (Sandbox Code Playgroud) 如果仍然引用了某些部分,python垃圾收集器是否会清除复合对象
例如
def foo():
A = [ [1, 3, 5, 7], [2, 4, 6, 8]]
return A[1]
B = foo()
Run Code Online (Sandbox Code Playgroud)
会A[0]被垃圾收集吗?
有没有办法通过代码确认相同的?
我刚做了一个有趣的测试:
~$ python3 # I also conducted this on python 2.7.6, with the same result
Python 3.4.0 (default, Apr 11 2014, 13:05:11)
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class Foo(object):
... def __add__(self, other):
... global add_calls
... add_calls += 1
... return Foo()
... def __iadd__(self, other):
... return self
...
>>> add_calls = 0
>>> a = list(map(lambda x:Foo(), range(6)))
>>> a[0] + a[1] + a[2]
<__main__.Foo object at 0x7fb588e6c400> …Run Code Online (Sandbox Code Playgroud) __call__每当您尝试调用对象时,都会调用Python的魔术方法.Cls()()因此等于Cls.__call__(Cls()).
函数是Python中的第一类对象,这意味着它们只是可调用对象(使用__call__).然而,__call__本身是一个函数,因此它也有__call__,这又都有自己的__call__,而这又都有自己的__call__.
因此Cls.__call__(Cls()),等于Cls.__call__.__call__(Cls())和再等同于Cls.__call__.__call__.__call__(Cls())等等等等.
这个无限循环如何结束?如何__call__实际执行代码?
当我今天浏览Python HMAC模块源代码时,我发现它包含全局变量_secret_backdoor_key.然后检查该变量以中断对象初始化.
代码看起来像这样
# A unique object passed by HMAC.copy() to the HMAC constructor, in order
# that the latter return very quickly. HMAC("") in contrast is quite
# expensive.
_secret_backdoor_key = []
class HMAC:
"""RFC 2104 HMAC class. Also complies with RFC 4231.
This supports the API for Cryptographic Hash Functions (PEP 247).
"""
blocksize = 64 # 512-bit HMAC; can be changed in subclasses.
def __init__(self, key, msg = None, digestmod = None):
"""Create a new …Run Code Online (Sandbox Code Playgroud) 单元测试模块时遇到了一个令人困惑的问题.该模块实际上是铸造值,我想比较这些值.
是有区别的使用比较==和is(部分,我小心的区别)
>>> 0.0 is 0.0
True # as expected
>>> float(0.0) is 0.0
True # as expected
Run Code Online (Sandbox Code Playgroud)
正如预期到现在,但这是我的"问题":
>>> float(0) is 0.0
False
>>> float(0) is float(0)
False
Run Code Online (Sandbox Code Playgroud)
为什么?至少最后一个对我来说真的很困惑.内部表示float(0)和float(0.0)应该是平等的.与之比较==正如预期的那样.
python floating-point python-2.7 python-3.x python-internals
通过查看CPython实现,似乎字符串的返回值split()是新分配的字符串列表.但是,由于字符串是不可变的,所以似乎可以通过指向偏移量从原始字符串中创建子字符串.
我是否正确理解了CPython的当前行为?是否有理由不选择此空间优化?我能想到的一个原因是父字符串在其所有子字符串都被释放之前无法释放.
为什么范围允许非默认参数(stop)遵循默认参数(start)?
例证:
>>> r = range(1, 2, 3)
>>> print(r.start, r.stop, r.step)
1 2 3
>>> r = range(10)
>>> print(r.start, r.stop, r.step)
0 10 1
Run Code Online (Sandbox Code Playgroud)
试图模仿签名是一个明显的违规行为:
def my_range(start=0, stop, end=1):
pass
Run Code Online (Sandbox Code Playgroud)
我知道它实现的事实C可能允许在Pythonland中违反的行为.
我猜这是为了使API更加用户友好,但我没有找到任何来源备份它(源代码并没有说明多少,而PEP 457只说明了多么range奇怪).有谁知道为什么这样做了?
在Python 2中,为什么旧样式类的实例仍然是实例,object即使它们没有显式继承object?
class OldClass:
pass
>>> isinstance(OldClass(), object)
True
Run Code Online (Sandbox Code Playgroud)
在测试之前,我会得出结论,isinstance(x, object) == True这意味着它x是一个子类object的实例,因此是新样式类的一个实例,但似乎Python 2中的所有对象都是实例object(是的,我知道声音有多明显) ).
进一步挖掘,我发现了一些看似奇怪的行为:
>>> issubclass(OldClass, object)
False
Run Code Online (Sandbox Code Playgroud)
我的印象isinstance(x, SomeClass)实际上相当于issubclass(x.__class__, SomeClass),但显然我错过了一些东西.
当天早些时候,我正在大量尝试使用docstrings和dis模块,并且遇到了一些我似乎找不到答案的东西.
首先,我创建一个test.py包含以下内容的文件:
def foo():
pass
Run Code Online (Sandbox Code Playgroud)
就是这样,没有别的.
然后我打开一个解释器来观察程序的字节码.你可以这样得到它:
code = compile(open('test.py').read(), '', 'exec')
Run Code Online (Sandbox Code Playgroud)
第一个参数是字符串形式的代码,第二个参数用于调试目的(将其留空即可),而第三个参数是模式.我都试过single和exec.结果是一样的.
在此之后,您可以使用反编译字节码dis.
>>> import dis
>>> dis.dis(code)
Run Code Online (Sandbox Code Playgroud)
字节码输出是这样的:
1 0 LOAD_CONST 0 (<code object foo at 0x10a25e8b0, file "", line 1>)
3 MAKE_FUNCTION 0
6 STORE_NAME 0 (foo)
9 LOAD_CONST 1 (None)
12 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
合理的,对于这样一个简单的脚本.它也是有道理的.
然后我尝试通过命令行编译它,如下所示:
$ python -m py_compile test.py
Run Code Online (Sandbox Code Playgroud)
这导致生成字节码并将其放置在test.pyc文件中.内容可以再次拆卸:
>>> import dis
>>> dis.dis(open('test.pyc').read())
Run Code Online (Sandbox Code Playgroud)
这是输出:
>> 0 ROT_THREE
1 <243> 2573
>> 4 …Run Code Online (Sandbox Code Playgroud) python ×10
python-internals ×10
python-3.x ×3
bytecode ×1
class ×1
disassembly ×1
hash ×1
isinstance ×1
nonetype ×1
optimization ×1
pyc ×1
python-2.7 ×1
python-2.x ×1
singleton ×1
split ×1
string ×1