Open felixcarmona opened 9 years ago
object.__class__.__name__
will always be "type"
- what did you meant to do there?
Is your intention roughly "delay object initialization" or "delay object creation"? It's not clear what's wrong with the regular way (lambda *args, **kwargs: Proxy(lambda: A(*args, **kwargs))
) ...
Doing something special in constructor (__new__
) only makes sense if you want subclasses. Do you really need that?
Otherwise just use a class decorator:
def lazy(klass):
def lazy_class(*args, **kwargs):
return Proxy(lambda: klass(*args, **kwargs))
lazy_class.__name__ = "lazy_" + klass.__name__
return lazy_class
@lazy
class A(object):
....
Now that I look again, your example seems fine (I didn't test it so it's a loose measure of "fine" :grin:).
You should replace class_ = type(object.__class__.__name__, (cls,), {})
with class_ = type(cls.__name__, (cls,), {})
for better __repr__
output.
thank you for your quick answer, which way is better? (I implemented my own because I didn't find your alternative in the doc or in tests, is there any reason to not include it?) regards!
I'm doing some tests: with the decorator's way, the returned object is an instance of "function" and not of the object, so, you cannot be abled to use it in some builtins like isinstance(a, A) With my first proposal, it works:
from lazy_object_proxy import Proxy
class LazyObject:
def __new__(cls, *args, **kwargs):
class_ = type(object.__name__, (cls,), {})
class_.__new__ = lambda cls_, *args_, **kwargs_: object.__new__(cls_)
return Proxy(lambda: class_(*args, **kwargs))
class B(LazyObject):
def __init__(self, x):
print("Init")
self.x = x
b = B(5)
print('GO')
print(b.x)
print(isinstance(b, B))
returns:
GO
Init
5
True
and
from lazy_object_proxy import Proxy
def lazy(klass):
def lazy_class(*args, **kwargs):
return Proxy(lambda: klass(*args, **kwargs))
lazy_class.__name__ = "lazy_" + klass.__name__
return lazy_class
@lazy
class A:
def __init__(self, x):
print("Init")
self.x = x
a = A(5)
print('GO')
print(a.x)
print(isinstance(a, A))
returns:
Traceback (most recent call last):
GO
File "test.py", line 19, in <module>
Init
print(isinstance(a, A))
5
TypeError: isinstance() arg 2 must be a type or tuple of types
You're right. I suppose we could have a metaclass that roughly does what you do in your example in a lazy_object_proxy.contrib
module (as opposed to just giving the complicated example in the readme).
Sounds good, thanks for your time, it's great to have contributors like you. You can close this issue if you want, Regards
edit: btw: You can still using the decorator:
from lazy_object_proxy import Proxy
def lazy(cls):
class Lazy:
def __new__(cls, *args, **kwargs):
original_class = type(object.__name__, (cls,), {})
original_class.__new__ = lambda cls_, *args_, **kwargs_: object.__new__(cls_)
return Proxy(lambda: original_class(*args, **kwargs))
lazy_class = type(cls.__name__, (cls, Lazy), {})
return lazy_class
@lazy
class B:
def __init__(self, x):
print("Init")
self.x = x
b = B(5)
print('GO')
print(b.x)
print(isinstance(b, B))
output:
GO
Init
5
True
I want to implement a new more unattended way to proxy objects, inheriting a LazyObject class instead of doing a = Proxy(lambda: A(5))
I'm doing this:
result:
What do you think about this implementation? do you think I've missed any concern? any way to implement this in C?
Regards