作为一个练习,主要是为了我自己的娱乐,我正在实现一个回溯包装解析器.对此的灵感是我想更好地了解hygenic宏如何在类似algol的语言中工作(与你通常在其中找到的语法免费lisp方言相对应).因此,通过输入的不同传递可能会看到不同的语法,因此缓存的解析结果无效,除非我还存储语法的当前版本以及缓存的解析结果.(编辑:使用键值集合的结果是它们应该是不可变的,但我不打算公开接口以允许它们被更改,因此可变或不可变集合都可以)
问题是python dicts不能作为其他dicts的键.即使使用元组(正如我将要做的那样)也无济于事.
>>> cache = {}
>>> rule = {"foo":"bar"}
>>> cache[(rule, "baz")] = "quux"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>>
Run Code Online (Sandbox Code Playgroud)
我想它必须一直是元组.现在python标准库提供了我所需要的,collections.namedtuple具有非常不同的语法,但可以用作键.继续上述会议:
>>> from collections import namedtuple
>>> Rule = namedtuple("Rule",rule.keys())
>>> cache[(Rule(**rule), "baz")] = "quux"
>>> cache
{(Rule(foo='bar'), 'baz'): 'quux'}
Run Code Online (Sandbox Code Playgroud)
好.但是我必须为我想要使用的规则中的每个可能的键组合创建一个类,这不是那么糟糕,因为每个解析规则确切地知道它使用了什么参数,因此可以同时定义该类作为解析规则的函数.
编辑:namedtuples 的另一个问题是它们是严格定位的.两个看起来应该不同的元组实际上可以是相同的:
>>> you = namedtuple("foo",["bar","baz"])
>>> me = namedtuple("foo",["bar","quux"])
>>> you(bar=1,baz=2) == me(bar=1,quux=2)
True
>>> bob = namedtuple("foo",["baz","bar"]) …Run Code Online (Sandbox Code Playgroud) 根据文件,
__new__()是一个静态方法(特殊的,因此您不需要声明它),它将请求实例的类作为其第一个参数.
它显然不是类方法,但通常看起来像一个,除了手动调用的任何客户端__new__需要显式传入类参数.例如:
>>> str.__new__()
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
str.__new__()
TypeError: str.__new__(): not enough arguments
>>> str.__new__(str)
''
Run Code Online (Sandbox Code Playgroud)
但是替代对象创建API -例如,所有八个备选datetime构造 - 是平时classmethodS,SO是datetime.now()按预期工作.
为什么这样__new__设置?
我理解是什么__new__(以及它与之有什么不同__init__)所以我对定义不感兴趣,我对何时以及如何使用感兴趣__new__.
文件说:
在一般情况下,你不应该需要重写
__new__,除非你继承一个不变型像str,int,unicode或tuple
但我无法想到使用其他情况__new__或如何正确使用它(例如,当子类化不可变类型或为什么在这种情况下需要它时).
那么,何时,为什么以及如何使用__new__?
我对用例很感兴趣,而不是它的用途(我知道它的作用).
所以我有一长串条件应该被证实是真的.if我没有把长条件链接起来,而是试图"创新"并且这样做,我认为这更具可读性.但我的问题是,这是最佳的做法吗?
或者有一种pythonic方式吗?PS:请回答替代方案,而不是回答"否",谢谢!
这是代码块:
def site_exists(site):
"""
returns the sitebean if it exists,
else returns false
"""
vpadmin_service = _get_vpadmin_service(site)
all_sites = VpAdminServiceUtil.getSites(vpadmin_service)
for site_listing in all_sites:
if site.getId():
#condition check
try:
assert site.getId() == site_listing.getId()
assert site.getName() == site_listing.getName()
assert site.getCustomer().getId() == site_listing.getCustomer().getId()
except AssertionError:
continue
#pass conditions
return site_listing
#no id, so just check for name and customer
else:
#condition check
try:
assert site.getName() == site_listing.getName()
assert site.getCustomer().getId() == site_listing.getCustomer().getId()
except AssertionError:
continue
#pass conditions
site.setId(site_listing.getId())
return …Run Code Online (Sandbox Code Playgroud) 希望这不是太基础,但......
假设我有一个基类pa(),并且我派生了从基类继承的类pai(),paj()等.
我想从基类pa()实例化一个对象:
>>> from pamod import *
>>> mypa = pa()
>>> mypa
<pamod.pa object at 0x28d4fd0>
>>>
Run Code Online (Sandbox Code Playgroud)
...然后根据某些操作将它(强制转换)推广到派生类:
>>> mypa.do(this)
>>> mypa
<pamod.pai object at 0x28d4fd0>
>>>
Run Code Online (Sandbox Code Playgroud)
基于"this"的值,mypa成为pai等的对象.
我知道我可以分配给对象了__class__.
迈帕足球俱乐部.
__class__=派
但是我想知道这是否真的是最好的方法.
根据我的方案,每个pai(例如)的实例都将作为基类pa的一个实例开始生活,所以pai的__init__方法可能会以某种方式超载,我猜.
见 这个 讨论.
彼得