Declaring a class with an instance of it inside in Python - python

Maybe the title is a little screwed up but is there a way to make an instance of a class inside the same class in Python?
Something like this:
class Foo:
foo = Foo()
I know that the interpreter says that Foo is not declared but is there a way to achieve this?
Update:
This is what I'm trying to do:
class NPByteRange (Structure):
_fields_ = [ ('offset', int32),
('lenght', uint32),
('next', POINTER(NPByteRange)) ]

The interpreter only minds if you try to do it in a context where Foo is not declared. There are contexts where it is. The simplest example is in a method:
>>> class Beer(object):
... def have_another(self):
... return Beer()
...
>>> x=Beer()
>>> x.have_another()
<__main__.Beer object at 0x10052e390>
If its important that the object be a property, you can just use the property builtin.
>>> class Beer(object):
... #property
... def another(self):
... return Beer()
...
>>> guinness=Beer()
>>> guinness.another
<__main__.Beer object at 0x10052e610>
Finally, if it's truly necessary that it be a class property, well, you can do that, too.

Related

Test an object is a subclass of the type of another instance

I have this code:
class Item:
def __init__(self,a):
self.a=a
class Sub(Item):
def __init__(self,a,b):
self.b=b
Item.__init__(self,a)
class SubSub(Sub):
def __init__(self,a,b,c):
self.c=c
Sub.__init__(self,a,b)
obj1=Item(1)
obj2=Sub(1,2)
obj3=SubSub(1,2,3)
Now I want to check if obj2 and obj3 are instances of classes that are subclasses of obj1 as well as simply subclasses of of Item.
Here is what I understand, I know that I can use the isinstance() to find if obj2 is Sub. and I know that I can use issubclass(Sub, Item). But let's say I didn't know what class obj2 was.
I tried using issubclass(type(obj2),Item) but that doesn't work, because type() returns a separate object that I don't really understand the workings of. And this is just one problem, although I figure that the answer to this question will help me solve some of the other problems that I am having.
Also I have tried using some of the special attributes to do this such as __class__ but I can't figure out how to do that either.
You'd need to extract the type of obj with the type() function:
isinstance(obj2, type(obj1))
Note that the second argument is the class, the first is the instance to test. type() is returning the actual class object here, not any separate object.
issubclass() works just fine for your usecase:
issubclass(type(obj2), Item)
Demo:
>>> class Item:
... def __init__(self,a):
... self.a=a
...
>>> class Sub(Item):
... def __init__(self,a,b):
... self.b=b
... Item.__init__(self,a)
...
>>> class SubSub(Sub):
... def __init__(self,a,b,c):
... self.c=c
... Sub.__init__(self,a,b)
...
>>> obj1=Item(1)
>>> obj2=Sub(1,2)
>>> obj3=SubSub(1,2,3)
>>> isinstance(obj2, type(obj1))
True
>>> issubclass(type(obj2), Item)
True
Note that if you re-defined the classes here, existing instances will not be updated to point to the new class objects. If type(obj2) doesn't work for you, then that means that the class used to produce it is not the same you are testing with now.
You can test if this the case by testing your assumptions; validate that the classes and instances are still in sync, for example:
>>> type(obj1) is Item
True
>>> type(obj2) is Sub
True
>>> type(obj3) is SubSub
True

In Python, class from which a given instance is inheriting a particular method

I know that in Python, given a class ClassA, with
inspect.getmembers(ClassA, predicate=inspect.ismethod)
I can iterate over the different methods present in ClassA. Inherited methods are also gathered, which is convenient in my case. But what I would need is, given a particular method method1 of ClassA, to get the class from which ClassA inherited method1. It might be ClassA itself, or any of its parents/grandparents. I thought I could recursively traverse the __bases__ attribute, looking for the method1 attribute at each step. But maybe this functionality is already implemented somewhere. Is there another way?
Look through the MRO (Method Resolution Order), using inspect.getmro() (which works on both old and new-style classes):
def class_for_method(cls, method):
return next((c for c in inspect.getmro(cls)
if method.__func__ in vars(c).values()), None)
There is currently no stdlib method to do this search for you, no.
Demo:
>>> import inspect
>>> def class_for_method(cls, method):
... return next((c for c in inspect.getmro(cls)
... if method.__func__ in vars(c).values()), None)
...
>>> class Base1(object):
... def foo(self): pass
...
>>> class Base2(object):
... pass
...
>>> class ClassA(Base1, Base2):
... pass
...
>>> class_for_method(ClassA, ClassA.foo)
<class '__main__.Base1'>
If no base class is found, the above expression returns None:
>>> class Bar:
... def spam(): pass
...
>>> class_for_method(ClassA, Bar.spam) is None
True

Is it possible to override `__name__` derived from object?

To get a string representation of a class name we can use obj.__class__.__name__ is it possible to overload these methods so that I can return my string instead of the actual class name?
Let's try! (Yes, this works):
>>> class Foo(object):
... pass
...
>>> obj = Foo()
>>> obj.__class__.__name__ = 'Bar'
>>> obj
<__main__.Bar object at 0x7fae8ba3af90>
>>> obj.__class__
<class '__main__.Bar'>
You could also have just done Foo.__name__ = 'Bar', I used obj.__class__.__name__ to be consistent with your question.
Yep.
class A:
def __init__(self):
self.__class__.__name__ = 'B'
But this seems like a bad idea.
You can do this:
>>> class Foo(object):
... def __init__(self):
... self.__class__.__name__ = "Bar"
...
>>> print Foo().__class__.__name__
Bar
Or you can make your own double underscore attribute.
>>> class Foo(object):
... __name__ = "Bar"
...
>>> print Foo().__name__
Bar
But why would you want to do this? I don't see any possible use for this. BTW, I realize this is not the same as __class__.__name__, but I don't think changing __class__.__name__ is generally a good idea.

"Programmatically" add stuff to a class?

I'm writing a class that has a dict containing int to method mappings. However setting the values in this dict results in the dict being populated with unbound functions.
class A:
def meth_a: ...
def meth_b: ...
...
map = {1: meth_a, 2: meth_b, ...}
for int in ...:
map[int] = meth_x
This doesn't work for a few reasons:
The methods aren't bound when the class is initialized because they're not in the class dict?
I can't bind the methods manually using __get__ because the class name isn't bound to any namespace yet.
So:
How can I do this?
Do I have to drop out of the class and define the dict after the class has been initialized?
Is it really necessary to call __get__ on the methods to bind them?
Update0
The methods will be called like this:
def func(self, int):
return self.map[int]()
Also regarding the numeric indices/list: Not all indices will be present. I'm not aware that one can do list([1]=a, [2]=b, [1337]=leet) in Python, is there an equivalent? Should I just allocate a arbitrary length list and set specific values? The only interest I have here is in minimizing the lookup time, would it really be that different to the O(1) hash that is {}? I've ignored this for now as premature optimization.
I'm not sure exactly why you're doing what you're doing, but you certainly can do it right in the class definition; you don't need __init__.
class A:
def meth_a(self): pass
m = {1: meth_a}
def foo(self, number):
self.m[number](self)
a = A()
a.foo(1)
An "unbound" instance method simply needs you to pass it an instance of the class manually, and it works fine.
Also, please don't use int as the name of a variable, either, it's a builtin too.
A dictionary is absolutely the right type for this kind of thing.
Edit: This will also work for staticmethods and classmethods if you use new-style classes.
First of all Don't use variable "map" since build in python function map will be fetched.
You need to have init method and initialize your dictionary in the init method using self. The dictionary right now is only part of the class, and not part of instances of the class. If you want instances of the class to have the dictionary as well you need to make an init method and initialize your dictionary there. So you need to do this:
def __init__(self):
self.mymap[int] = self.meth_x
or if you want the dictionary to be a class variable, then this:
def __init__(self):
A.mymap[int] = self.meth_x
It's not totally clear just what you're trying to do. I suspect you want to write code something like
class Foo(object):
def __init__(self, name):
self.name = name
def method_1(self, bar):
print self.name, bar
# ... something here
my_foo = Foo('baz')
my_foo.methods[1]('quux')
# prints "baz quux"
so, that methods attribute needs to return a bound instance method somehow, but without being called directly. This is a good opportunity to use a descriptor. We need to do something that will return a special object when accessed through an instance, and we need that special object to return a bound method when indexed. Let's start from the inside and work our way out.
>>> import types
>>> class BindMapping(object):
... def __init__(self, instance, mapping):
... self.instance, self.mapping = instance, mapping
...
... def __getitem__(self, key):
... func = self.mapping[key]
... if isinstance(func, types.MethodType):
... return types.MethodType(func.im_func, self.instance, func.im_class)
... else:
... return types.MethodType(func, self.instance, type(self))
...
We're just implementing the barest minimum of the mapping protocol, and deferring completely to an underlying collection. here we make use of types.MethodType to get a real instance method when needed, including binding something that's already an instance method. We'll see how that's useful in a minute.
We could implement a descriptor directly, but for the purposes here, property already does everything we need out of a descriptor, so we'll just define one that returns a properly constructed BindMapping instance.
>>> class Foo(object):
... def method_1(self):
... print "1"
... def method_2(self):
... print "2"
...
... _mapping = [method_1, method_2]
...
... #property
... def mapping(self):
... return BindMapping(self, self._mapping)
...
Just for kicks, we also throw in some extra methods outside the class body. Notice how the the methods added inside the class body are functions, just like functions added outside; methods added outside the class body are actual instance methods (although unbound).
>>> def method_3(self):
... print "3"
...
>>> Foo._mapping.append(method_3)
>>> Foo._mapping.append(Foo.method_1)
>>> map(type, Foo._mapping)
[<type 'function'>, <type 'function'>, <type 'function'>, <type 'instancemethod'>]
And it works as advertised:
>>> f = Foo()
>>> for i in range(len(f._mapping)):
... f.mapping[i]()
...
1
2
3
1
>>>
This seems kind of convoluted to me. What is the ultimate goal?
If you really want do to this, you can take advantage of the fact that the methods are alreaday contained in a mapping (__dict__).
class A(object):
def meth_1(self):
print("method 1")
def meth_2(self):
print("method 2")
def func(self, i):
return getattr(self, "meth_{}".format(i))()
a = A()
a.func(2)
This pattern is found in some existing library modules.

Get name of current class?

How do I get the name of the class I am currently in?
Example:
def get_input(class_name):
[do things]
return class_name_result
class foo():
input = get_input([class name goes here])
Due to the nature of the program I am interfacing with (vistrails), I cannot use __init__() to initialize input.
obj.__class__.__name__ will get you any objects name, so you can do this:
class Clazz():
def getName(self):
return self.__class__.__name__
Usage:
>>> c = Clazz()
>>> c.getName()
'Clazz'
Within the body of a class, the class name isn't defined yet, so it is not available. Can you not simply type the name of the class? Maybe you need to say more about the problem so we can find a solution for you.
I would create a metaclass to do this work for you. It's invoked at class creation time (conceptually at the very end of the class: block), and can manipulate the class being created. I haven't tested this:
class InputAssigningMetaclass(type):
def __new__(cls, name, bases, attrs):
cls.input = get_input(name)
return super(MyType, cls).__new__(cls, name, bases, newattrs)
class MyBaseFoo(object):
__metaclass__ = InputAssigningMetaclass
class foo(MyBaseFoo):
# etc, no need to create 'input'
class foo2(MyBaseFoo):
# etc, no need to create 'input'
PEP 3155 introduced __qualname__, which was implemented in Python 3.3.
For top-level functions and classes, the __qualname__ attribute is equal to the __name__ attribute. For nested classes, methods, and nested functions, the __qualname__ attribute contains a dotted path leading to the object from the module top-level.
It is accessible from within the very definition of a class or a function, so for instance:
class Foo:
print(__qualname__)
will effectively print Foo.
You'll get the fully qualified name (excluding the module's name), so you might want to split it on the . character.
However, there is no way to get an actual handle on the class being defined.
>>> class Foo:
... print('Foo' in globals())
...
False
You can access it by the class' private attributes:
cls_name = self.__class__.__name__
EDIT:
As said by Ned Batchelder, this wouldn't work in the class body, but it would in a method.
EDIT: Yes, you can; but you have to cheat: The currently running class name is present on the call stack, and the traceback module allows you to access the stack.
>>> import traceback
>>> def get_input(class_name):
... return class_name.encode('rot13')
...
>>> class foo(object):
... _name = traceback.extract_stack()[-1][2]
... input = get_input(_name)
...
>>>
>>> foo.input
'sbb'
However, I wouldn't do this; My original answer is still my own preference as a solution. Original answer:
probably the very simplest solution is to use a decorator, which is similar to Ned's answer involving metaclasses, but less powerful (decorators are capable of black magic, but metaclasses are capable of ancient, occult black magic)
>>> def get_input(class_name):
... return class_name.encode('rot13')
...
>>> def inputize(cls):
... cls.input = get_input(cls.__name__)
... return cls
...
>>> #inputize
... class foo(object):
... pass
...
>>> foo.input
'sbb'
>>>
#Yuval Adam answer using #property
class Foo():
#property
def name(self):
return self.__class__.__name__
f = Foo()
f.name # will give 'Foo'
I think, it should be like this:
class foo():
input = get_input(__qualname__)
import sys
def class_meta(frame):
class_context = '__module__' in frame.f_locals
assert class_context, 'Frame is not a class context'
module_name = frame.f_locals['__module__']
class_name = frame.f_code.co_name
return module_name, class_name
def print_class_path():
print('%s.%s' % class_meta(sys._getframe(1)))
class MyClass(object):
print_class_path()
I'm using python3.8 and below is example to get your current class name.
class MyObject():
#classmethod
def print_class_name(self):
print(self.__name__)
MyObject.print_class_name()
Or without #classmethod you can use
class ClassA():
def sayhello(self):
print(self.getName())
def getName(self):
return self.__class__.__name__
ClassA().sayhello()
Hope that helps others !!!

Categories

Resources