给定一个instance、
inst
和一个包含slot名称的字符串
attr
,如何获取attr
上插槽inst
的值?
当然,如果
attr
是一个符号而不是字符串,我通常只会使用(slot-value inst attr)
,但似乎我需要包信息才能正确调用intern
(见下文)。
(defpackage :pack1
(:use :common-lisp)
(:export :*inst*))
(in-package :pack1)
(defclass temp-class ()
((temp-slot :initarg :temp-slot)))
(defvar *inst* (make-instance 'temp-class :temp-slot "value"))
(defpackage :pack2
(:use :common-lisp :pack1)
(:import-from :pack1 :temp-class))
(in-package :pack2)
(let ((inst *inst*) ; In the real example, inst gets defined outside my control,
; in yet another package
(attr "temp-slot"))
(format t "Given package name: ~S; " ; prints fine
(slot-value inst (intern (string-upcase attr) :pack1)))
(format t "No package name: ~S; " ; signals an error
(slot-value inst (intern (string-upcase attr)))))
py-format
的 Common Lisp 端口
Python 的 {}
格式。要实现 Python .
运算符 (getattr
),我需要将
点后面的字符串插入点前面的对象上的槽中。
给定一个实例、inst 和一个包含插槽名称的字符串 attr,如何获取 inst 上插槽 attr 的值?
插槽没有字符串作为插槽名称,而是符号。由于槽名称可以是任意符号,因此如果您只有字符串,则没有通用方法来获取槽值。
CL-USER 124 > (defclass foo ()
((s) ; the slot-name is cl-user::s
(system::s) ; the slot-name is system::s
(#:s))) ; the slot-name is #:s
#<STANDARD-CLASS FOO 413054236B>
最后一个插槽名称是一个未驻留的符号。它没有包装。 因此,如果您没有将其存储在某个地方,您就无法以任何方式查找它。
CL-USER 125 > (make-instance 'foo)
#<FOO 402013F043>
CL-USER 126 > (describe *)
#<FOO 402013F043> is a FOO
S #<unbound slot>
S #<unbound slot>
S #<unbound slot>
如您在上面看到的,它有三个插槽。每个符号都有名称
s
,但实际上是不同的符号。
您可以通过内省获取插槽名称:
CL-USER 127 > (mapcar #'slot-definition-name
(class-direct-slots (find-class 'foo)))
(S SYSTEM::S #:S)
有关便携式功能,请参阅CLOSER-MOP。