从@encoded类型字符串中解码类(Decode Class from @encoded type string)
Objective-C的
@encode
生成C字符串以表示任何类型,包括基本类和类,如下所示:NSLog(@"%s", @encode(int)); // i NSLog(@"%s", @encode(float)); // f NSLog(@"%s", @encode(CGRect)); // {CGRect={CGPoint=ff}{CGSize=ff}} NSLog(@"%s", @encode(NSString)); // {NSString=#} NSLog(@"%s", @encode(UIView)); // {UIView=#@@@@fi@@I{?=b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b6b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b3b1b1b1b2b2b1}}
所以,我可以使用
@encode(ClassName)
得到一个有意义的类的编码(一个包含类名),但它的格式与一般struct
的编码相同(如上例)。现在,我的问题是,鉴于任何 (当然有效)类型编码,是否有可能找出编码是否为Objective-C类,如果是,获取与该编码相对应的
Class
对象?当然,我可能只是尝试从类型编码中解析类名,并使用
NSClassFromString
从类中获取类,但这听起来不像是正确的方式,或者特别是性能高效。 这是否是实现这一目标的最佳方式?Objective-C's
@encode
produces C strings to represent any type, including primitives, and classes, like so:NSLog(@"%s", @encode(int)); // i NSLog(@"%s", @encode(float)); // f NSLog(@"%s", @encode(CGRect)); // {CGRect={CGPoint=ff}{CGSize=ff}} NSLog(@"%s", @encode(NSString)); // {NSString=#} NSLog(@"%s", @encode(UIView)); // {UIView=#@@@@fi@@I{?=b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b6b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b3b1b1b1b2b2b1}}
So, I can get a meaningful encoding of a class (one that contains the class name) using
@encode(ClassName)
, but it's also in the same format as the encoding of a genericstruct
(as in the above example).Now, my question is, given any (valid of course) type encoding, is it possible to find out whether the encoding is of an Objective-C class, and if so, to get the
Class
object that corresponds to that encoding?Of course, I probably could just try to parse the class name out of the type encoding, and get the class from that using
NSClassFromString
, but that just doesn't sound like the right way to do it, or particularly performance-efficient. Is this really the best way to achieve this?
原文:https://stackoverflow.com/questions/18161519
最满意答案
不,
is
一个直接的指针比较,并且id
只是将对象的地址转换为long
。来自
ceval.c
:case PyCmp_IS: res = (v == w); break; case PyCmp_IS_NOT: res = (v != w); break;
v
和w
在这里只是PyObject *
。来自
bltinmodule.c
:static PyObject * builtin_id(PyObject *self, PyObject *v) { return PyLong_FromVoidPtr(v); } PyDoc_STRVAR(id_doc, "id(object) -> integer\n\ \n\ Return the identity of an object. This is guaranteed to be unique among\n\ simultaneously existing objects. (Hint: it's the object's memory address.)");
No,
is
is a straight pointer comparison, andid
just returns the address of the object cast to along
.From
ceval.c
:case PyCmp_IS: res = (v == w); break; case PyCmp_IS_NOT: res = (v != w); break;
v
andw
here are simplyPyObject *
.From
bltinmodule.c
:static PyObject * builtin_id(PyObject *self, PyObject *v) { return PyLong_FromVoidPtr(v); } PyDoc_STRVAR(id_doc, "id(object) -> integer\n\ \n\ Return the identity of an object. This is guaranteed to be unique among\n\ simultaneously existing objects. (Hint: it's the object's memory address.)");
相关问答
更多-
你的问题有点泛泛。 尽管__setstate__一些stdlib特定的方法(例如pickle等使用的__setstate__和__getstate__等,但是它是pickle模块的协议,而不是语言协议),所以有一个全面的“特殊方法” 列表 。 如果您想确切知道解释器的功能,您可以使用dis模块来反汇编字节码: >>> import dis >>> def my_func(a): ... return a + 2 ... >>> dis.dis(my_func) 2 0 LO ...
-
是没有的方法。 你不能覆盖它,这是故意的。 整个问题的关键is它告诉你两个表达式是否引用相同的值。 所以根据定义,它必须是两个不同的值。 所以没有必要重写它。 正如文件所说: 运算符is和not is测试对象的身份:当且仅当x和y是相同的对象时, x is y是真的。 ( 数据模型文档中有更多内容。) 另外, is不比较id的结果。 id只是被定义为返回“一个整数,该整数在其生命周期中保证是唯一的并且是不变的”。 这意味着肯定可以使用id ,但我不知道它在哪里执行。 也就是说,在CPython中,它在覆盖i ...
-
不, is一个直接的指针比较,并且id只是将对象的地址转换为long 。 来自ceval.c : case PyCmp_IS: res = (v == w); break; case PyCmp_IS_NOT: res = (v != w); break; v和w在这里只是PyObject * 。 来自bltinmodule.c : static PyObject * builtin_id(PyObject *self, PyObject *v) { return ...
-
定义元类上的方法。 class MC(type): def __rshift__(self, other): return something(self, other) class C(object): __metaclass__ = MC print C >> None Define the method on the metaclass. class MC(type): def __rshift__(self, other): return something(self ...
-
为什么Python有__ne__运算符方法而不是__eq__?(Why does Python have an __ne__ operator method instead of just __eq__?)[2023-12-11]
SQLAlchemy是一个很好的例子。 对于未初学者,SQLAlchemy是一个ORM,并使用Python表达式生成SQL语句。 在一个表达式中, meta.Session.query(model.Theme).filter(model.Theme.id == model.Vote.post_id) model.Theme.id == model.VoteWarn.post_id不返回一个布尔值,而是一个最终产生一个SQL查询的对象,如WHERE theme.id = vote.post_id 。 逆将产 ... -
您需要使用__getitem__方法 。 >>> class MyClass: ... def __getitem__(self, key): ... return key * 2 ... >>> myobj = MyClass() >>> myobj[3] 6 如果您要设置值,那么您也需要实现__setitem__方法 ,否则会发生这种情况: >>> myobj[5] = 1 Traceback (most recent call last): File "
", ... -
Python“魔术方法”,用于自定义in运算符的行为(Python “magic method” for customizing the behaviour of the in operator)[2022-07-10]
__contains__是您正在寻找的方法 从这个页面 : 对于定义__contains__()方法的用户定义类,当且仅当y.__contains__(x)为真时, y.__contains__(x)为真。 对于没有定义__contains__()但是定义__iter__()用户定义的类,如果在迭代y产生一些带有x == z值z ,则x in y为真。 如果在迭代期间引发异常,则就好像在异常中引发异常一样。 最后,尝试了旧式迭代协议:如果一个类定义了__getitem__() ,则x in y为真,当且仅当 ... -
使用运算符模块自动构建魔术方法[关闭](Using the operator module to automate the construction of magic methods [closed])[2021-12-25]
这是工作代码: import operator as op class Expr(object): def __init__(self, func=lambda x: x): self.expr = func def __call__(self, x): return self.expr(x) def factory(name): def operator(self, other): return Expr(lambda x: ... -
它是__contains__() : >>> y = [5, 4, 3, 2, 1] >>> y.__contains__(3) True >>> y.__contains__(6) False It's __contains__(): >>> y = [5, 4, 3, 2, 1] >>> y.__contains__(3) True >>> y.__contains__(6) False
-
没有and / or操作符的钩子,没有(因为它们短路),Python中没有xor操作符。 __and__和__or__用于按位 & | 运营商 ,分别。 not等价的按位运算符是~ (反转),由__invert__方法处理,而__xor__覆盖^按位运算符。 not 根据对象的真值进行操作 。 如果你有一个容器,给它一个__len__方法 ,如果没有给它一个__bool__方法 。 任何一个被咨询以确定一个对象是否应该被认为是“真实的”; not颠倒该测试的结果。 因此,如果__bool__返回True或_ ...