來自Python標準庫的命名元組不需要類聲明。您可以使用函數調用來創建類。
=> (import [collections [namedtuple]])
=> (namedtuple 'Point3D '[x y z])
<class '__console__.Point3D'>
=> (setv Point3D _) ; Hy's repl sets _ to the previous result.
=> (Point3D 1 2 3)
Point3D(x=1, y=2, z=3)
命名元組實例是不可變的,就像普通的Python元組一樣。你不能分配給他們。
Python允許您在大多數對象上設置任意屬性。以下是Hy中的一個例子。
=> (setv spam (fn[]))
=> (setv spam.x 7)
=> spam.x
7
在上面的例子中,我在一個空的函數對象上設置了一個屬性x
。儘管如此,一些對象沒有屬性字典。您可以使用__slots__
語法自己創建這些對象。 (請參見Python documentation瞭解它的工作原理。)
在Python(和Hy)self
中不存在類聲明中,只存在於方法中,因爲它是第一個參數。這就是爲什麼你不能分配給它。你可以直接使用setv
這個名字,但是這個名字應該放在類字典中,而不是在任何特定的情況下。
=> (defclass Foo []
... (setv class-foo 7) ; lives in the class dict
... (defn __init__ [self foo]
... (setv self.foo foo))) ; lives in the instance dict
=> Foo.class-foo
7
=> (. (Foo 12) foo) ; the (.) form accesses attributes.
12
=> (. (Foo 12) class-foo) ; not in the instance, so look in its class
7
海蘭還沒有對Python的類型註釋的語法。 NamedTuple
元類使用這些。在某些情況下,您可以通過自己創建__annotations__
字典來解決此問題。
(import [collections [OrderedDict]]
[typing [NamedTuple]])
(defclass Key [NamedTuple]
(setv (get (vars) '__annotations__)
(doto (OrderedDict)
(assoc 'KEY KEY
'IDX IDX
'END END))))
這應該工作一樣的Python
class Key(NamedTuple):
KEY: KEY
IDX: IDX
END: END
雖然它實際上編譯爲更多的東西一樣
class Key(NamedTuple):
:G_1235 = OrderedDict()
:G_1235[HySymbol('KEY')] = KEY
:G_1235[HySymbol('IDX')] = IDX
:G_1235[HySymbol('END')] = END
vars()[HySymbol('__annotations__')] = :G_1235
還有其他的方法來創建海蘭的OrderedDict
,但這是最直接的之一。我們需要訂購註釋字典,因爲訂購了NamedTuple
。
A HySymbol
是一個Python字符串(子類),在大多數情況下都是一樣的。 :G_1235
是Hy gensym的名字。這些不是Python有效的標識符,但Hy編譯爲Python抽象語法樹,AST將接受類似的名稱。你可以親自看看Hy是如何編譯repl的,--spy
選項或(disassemble ...)
函數用於AST本身,或者它的近似Python等價物。
您還可以通過指派給您在課程正文註釋的名稱setv
來爲NamedTuple
提供默認值。
如果你對Python的3.6+(你會被給予NamedTuple
元類),那麼你可以使用kwargs作出OrderedDict
,由於PEP 468。在不保證kwargs順序的早期版本中,不要使用OrderedDict
。
在海蘭,
(defclass Foo [NamedTuple]
(setv (get (vars) '__annotations__)
(OrderedDict :name str
:ID int)
name "foo"
ID 42))
注意,一個setv
可以分配多對。最後兩對由元類使用,默認值爲NamedTuple
。
在REPL
=> (Foo)
Foo(name='foo', ID=42)
=> (Foo "bar")
Foo(name='bar', ID=42)
=> _.ID
42
可以在實際上建立在Python 3.6新的命名元組使用'typing.NamedTuple'雖然。請參閱[這裏](https://docs.python.org/3/library/typing.html#typing.NamedTuple)。 – bjd2385
@ bjd2385哦,這是一個新功能。它使用元類和類型註釋。 Hy還沒有支持Python的類型註釋,所以我不認爲這個等價物可以在Hy中工作。我會用解決方法更新答案。 – gilch
@ bjd2385請參閱上面的解決方法 – gilch