给定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)))))
intern
在不同的包中创建符号而不是定义类的符号。intern
之外有)我正在py-format
使用Common Lisp端口
Python的{}
- 格式化。要实现Python .
运算符(getattr
),我需要转换
将点后面的字符串插入点之前的对象上的插槽中。
答案 0 :(得分:3)
给定一个实例,inst和一个包含插槽名称的字符串attr,如何在inst上获取slot 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。