我有一个返回a的类方法CGSize,我想通过Objective-C运行时函数调用它,因为我将类和方法名称作为字符串值.
我正在使用XCode 4.2中的ARC标志进行编译.
方法签名:
+(CGSize)contentSize:(NSString *)text;
Run Code Online (Sandbox Code Playgroud)
我尝试的第一件事是用objc_msgSend这样调用它:
Class clazz = NSClassFromString(@"someClassName);
SEL method = NSSelectorFromString(@"contentSize:");
id result = objc_msgSend(clazz, method, text);
Run Code Online (Sandbox Code Playgroud)
这与"EXC_BAD_ACCESS"崩溃并且没有堆栈跟踪.我首先使用了这个,因为文档objc_msgSend说,
当遇到一个方法调用,编译器生成到的功能之一的呼叫
objc_msgSend,objc_msgSend_stret,objc_msgSendSuper,或objc_msgSendSuper_stret.[...]使用objc_msgSendSuper_stret和发送具有数据结构作为返回值的方法objc_msgSend_stret.
接下来,我用objc_msgSend_stret这样的:
Class clazz = NSClassFromString(@"someClassName);
SEL method = NSSelectorFromString(@"contentSize:");
CGSize size = CGSizeMake(0, 0);
objc_msgSend_stret(&size, clazz, method, text);
Run Code Online (Sandbox Code Playgroud)
使用上面的签名给出了以下两个编译器错误和两个警告:
错误:自动引用计数问题:ARC不允许将非Objective-C指针类型'CGSize*'(又名'struct CGSize*')隐式转换为'id'
警告:语义问题:不兼容的指针类型将'CGSize*'(又名'struct CGSize*')传递给'id'类型的参数
错误:自动引用计数问题:ARC不允许将Objective-C指针隐式转换为"SEL"
警告:语义问题:不兼容的指针类型将'__unsafe_unretained Class'传递给'SEL'类型的参数
如果我查看方法的声明,它是:
OBJC_EXPORT void objc_msgSend_stret(id self, SEL op, ...)
__OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
Run Code Online (Sandbox Code Playgroud)
这与 …
struct objective-c objective-c-runtime class-method automatic-ref-counting
我想在类创建时自动运行一些可以调用其他类方法的代码.我没有在类声明本身中找到这样做的方法,并最终创建一个@classmethod被调用__clsinit__并在类声明后立即从定义范围调用它.是否有一个我可以定义的方法,以便在创建类对象后自动调用它?
我有一个类将字典转换为这样的对象
class Dict2obj(dict):
__getattr__= dict.__getitem__
def __init__(self, d):
self.update(**dict((k, self.parse(v))
for k, v in d.iteritems()))
@classmethod
def parse(cls, v):
if isinstance(v, dict):
return cls(v)
elif isinstance(v, list):
return [cls.parse(i) for i in v]
else:
return v
Run Code Online (Sandbox Code Playgroud)
当我尝试制作对象的深层副本时,我收到了此错误
import copy
my_object = Dict2obj(json_data)
copy_object = copy.deepcopy(my_object)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py", line 172, in deepcopy
copier = getattr(x, "__deepcopy__", None)
KeyError: '__deepcopy__'
Run Code Online (Sandbox Code Playgroud)
但是我在类I中重写getattr函数Dict2obj能够进行深层复制操作.见下面的例子
class Dict2obj(dict):
__getattr__= dict.__getitem__
def __init__(self, d):
self.update(**dict((k, self.parse(v))
for k, v in d.iteritems()))
def __getattr__(self, key): …Run Code Online (Sandbox Code Playgroud) 我认为以下代码会导致错误,因为据我所知,Python 类中的方法必须将“self”(或任何其他标签,但按照约定是“self”)作为其第一个参数,或者如果使用了@classmethod装饰器,则为“cls”或类似名称,如果使用了装饰器,则为 none @staticmethod。
为什么我在终端中使用 Python 3.5 运行它没有错误,即使test_method不满足这些要求?它似乎作为静态方法工作正常,但没有装饰器。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
class MyClass:
def test_method(args):
print(args[1])
@staticmethod
def static_method():
print("static_method")
@classmethod
def class_method(cls):
print("class_method")
def main(args):
MyClass.test_method(args)
if __name__ == '__main__':
sys.exit(main(sys.argv))
Run Code Online (Sandbox Code Playgroud)
输出:
$ python3 testscript.py "testing"
$ testing
Run Code Online (Sandbox Code Playgroud)
编辑:
我的问题也可以用不同的措辞,将注意力从self和转移到@staticmethod:“我怎么会在没有 @staticmethod 装饰器的情况下得到一个看似有效的静态方法?”
我正在使用SQLAlchemy作为ORM的Pyramid应用程序.我试图用类方法测试模型:
# this is essentially a global used by all the models
Session = scoped_session(sessionmaker(autocommit=False))
class Role(Base):
__tablename__ = 'role'
id = sa.Column(sa.types.Integer, primary_key=True)
name = sa.Column(sa.types.Text, unique=True, nullable=False)
def __init__(self, **kwargs):
super(Role, self).__init__(**kwargs)
@classmethod
def find_all(self):
return Session.query(Role).order_by(Role.name).all()
Run Code Online (Sandbox Code Playgroud)
我正在使用factory_boy进行测试,以下是我尝试设置测试工厂的方法:
import factory
from factory.alchemy import SQLAlchemyModelFactory
from sqlalchemy.orm import scoped_session, sessionmaker
from zk.model.meta import Base
from zk.model.role import Role
session = scoped_session(sessionmaker())
engine = create_engine('sqlite://')
session.configure(bind=engine)
Base.metadata.create_all(engine)
class RoleFactory(SQLAlchemyModelFactory):
FACTORY_FOR = Role
FACTORY_SESSION = session
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试调用RoleFactory.find_all()测试时,我收到一个错误: …
在OCMockito中,使用NSProxy实现测试双精度.实例中的双重实现-respondsToSelector:如下:
- (BOOL)respondsToSelector:(SEL)aSelector {
return [_mockedClass instancesRespondToSelector:aSelector];
}
Run Code Online (Sandbox Code Playgroud)
但是对于一个类的实现-respondsToSelector:这样的双重实现:
- (BOOL)respondsToSelector:(SEL)aSelector {
return [_mockedClass respondsToSelector:aSelector];
}
Run Code Online (Sandbox Code Playgroud)
这一切都适用于32位运行时.例如,如果_mockedClass是[NSString class],则代理正确回答它响应选择器+pathWithComponents:
但在64位运行时,它崩溃了:
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: EXC_I386_GPFLT
Application Specific Information:
objc[1868]: GC: forcing GC OFF because OBJC_DISABLE_GC is set
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libobjc.A.dylib 0x00007fff95cbffc6 cache_getImp + 6
1 libobjc.A.dylib 0x00007fff95ccd1dc lookUpImpOrForward + 50
2 libobjc.A.dylib 0x00007fff95ccd198 lookUpImpOrNil + …Run Code Online (Sandbox Code Playgroud) 我在我写的这个元类装饰器上应用装饰器的实现有问题:
def decorateAll(decorator):
class MetaClassDecorator(type):
def __new__(meta, classname, supers, classdict):
for name, elem in classdict.items():
if type(elem) is FunctionType:
classdict[name] = decorator(classdict[name])
return type.__new__(meta, classname, supers, classdict)
return MetaClassDecorator
Run Code Online (Sandbox Code Playgroud)
这是我使用元类的类:
class Account(object, metaclass=decorateAll(Counter)):
def __init__(self, initial_amount):
self.amount = initial_amount
def withdraw(self, towithdraw):
self.amount -= towithdraw
def deposit(self, todeposit):
self.amount += todeposit
def balance(self):
return self.amount
Run Code Online (Sandbox Code Playgroud)
当我将一个装饰器传递给装饰器元类时,一切似乎都运行良好:
def Counter(fun):
fun.count = 0
def wrapper(*args):
fun.count += 1
print("{0} Executed {1} times".format(fun.__name__, fun.count))
return fun(*args)
return wrapper
Run Code Online (Sandbox Code Playgroud)
但是当我使用以这种方式实现的装饰器时:
class Counter():
def __init__(self, …Run Code Online (Sandbox Code Playgroud) 我在python中的某个类中编写了一个函数,人们建议我向这个函数添加一个@classmethod装饰器.
我的代码:
import random
class Randomize:
RANDOM_CHOICE = 'abcdefg'
def __init__(self, chars_num):
self.chars_num = chars_num
def _randomize(self, random_chars=3):
return ''.join(random.choice(self.RANDOM_CHOICE)
for _ in range(random_chars))
Run Code Online (Sandbox Code Playgroud)
建议的更改:
@classmethod
def _randomize(cls, random_chars=3):
return ''.join(random.choice(cls.RANDOM_CHOICE)
for _ in range(random_chars))
Run Code Online (Sandbox Code Playgroud)
我几乎总是只使用这个_randomize功能.
我的问题是:添加到classmethod装饰器的功能有什么好处?
我试图多次使用类方法的结果,而不进行获得结果所需的繁重计算。
我看到以下选项。你认为哪些是正确的,或者更像 Pythonic?
每一种的优点和缺点是什么?
class Test:
def __init__(self, *args):
# do stuff
@property
def new_method(self):
try:
return self._new_property
except AttributeError:
# do some heavy calculations
return self._new_property
Run Code Online (Sandbox Code Playgroud)
from functools import lru_cache
class Test:
def __init__(self, *args):
# do stuff
@property
@lru_cache()
def new_method(self):
# do some heavy calculations
return self._new_property
Run Code Online (Sandbox Code Playgroud)
from django.utils.functional import cached_property
class Test:
def __init__(self, *args):
# do stuff
@cached_property
def new_method(self):
# do some heavy calculations
return self._new_property
Run Code Online (Sandbox Code Playgroud) class-method ×10
python ×7
objective-c ×3
class ×2
decorator ×2
factory-boy ×1
initializer ×1
metaclass ×1
methods ×1
nsproxy ×1
properties ×1
python-2.7 ×1
sqlalchemy ×1
struct ×1