Python: Create a member that is a instance of its class - python

I am very confused that I did not directly found a topic about my concern:
I got the class RoadMark. In this class, I wanna create a member that is a specific instance of that class. But I am not able to call the constructor.
I tried:
calling the init function (but it has no return, so its worthless)
define the member as a function with the #property attribute (but these returns cannot have members, so worthless for an object)
Trying "solid = self.RoadMark..." (also not working)
Using a factory function to create the object (but in the method, RoadMark is also not defined)
Is there a way to solve my problem or do I have to outsource the "solid" variable?
Kind regards

You can assign it to the class member after the class definition.
class RoadMark:
...
RoadMark.solid = RoadMark()

Python code is executed as it is encountered. When the interpreter encounters the line class RoaMark:, it starts creating a new class object. Then it starts to run the code inside the class body to determine the attributes of the class. When the code in the body is running, the class object does not exist yet, so you can't access it. What you can do is wait until the class is created before assigning an attribute to it:
class RoaMark:
...
RoaMark.solid = RoaMark(...)

Related

How do I create an instance of a nested class from within that class in Python?

class ExampleClass():
def Example(self):
self.nestedinstance = self.NestedClass()
self.nestedinstance.makenew()
class NestedClass():
def makenew(self):
newclass = NestedClass()
ExampleClass().Example()
When I run the above code I get the exception: name 'NestedClass' is not defined
Is there a different way to do this with a nested class or have I done something wrong?
You ideally want to be using classmethods if creating a new instance, this is an example of how you'd do it:
class NestedClass():
#classmethod
def makenew(cls):
newclass = cls()
Alternatively if you wanted to create an instance using the current instance (for example if you needed to pass in some arguments), then you can get the class by using type(self) or self.__class__.
class NestedClass():
def makenew(self):
newclass = type(self)()
Without knowing your use case though, this may not be what you're after.
Your error comes from how python handles classes.
When it encounters a class statement, the body of the class is run, and the names it defines are placed in a separate namespace, which will eventually become the class __dict__. The class object is not created and bound to its name until (well) after the body has run. That means that when you put class NestedClass: inside the body of class ExampleClass:, ExampleClass does not exist yet, and neither does NestedClass. Indirectly because of this, all the new class namespaces live in the top level available namespace (e.g. global or function), and are not actually nested within one another.
As a consequence of this order of operations, class bodies are not aware of the namespaces of surrounding classes at all. So the namespace of NestedClass looks out to the global namespace, not to the __dict__ of ExampleClass, as you might expect coming from say Java. A class defined in a function would be able to see the functions local namespace before globals, but still not that of an enclosing class.
And so, the line newclass = NestedClass() raises an error. The name NestedClass does not exist in the function's namespace, or in the global namespace. There are three simple workarounds available:
Use the staticly scoped __class__:
newclass = __class__()
Refer to the class by its global name:
newclass = ExampleClass.NestedClass()
Don't use nested classes in Python. This is generally the preferred approach. Just move NestedClass to the top level. Then your makenew method will work without modification, and ExampleClass.Example can refer to NestedClass directly instead of as self.NestedClass.

How to call non abstract method in a abstract class?

I have an abstract class in python and want to call non-abstract methods in it. Is it possible to do it?
from abc import ABC, abstractmethod
class MyAbstract(ABC):
# Can I call method get_state() from get_current() ?
def get_state():
get_current() # gives me error?
def get_current():
#abstractmethod
def get_time():
I have another python file, Temp.py implement this interface.
In Temp.py, I call the get_state using MyAbstract.get_state(), I get the error stating that get_current() is undefined.
Not sure why.
Any help is appreciated.
In general, all methods have a namespace which is the class or object they're attached to. If you have an instance of a class floating around (e.g. self, most of the time), you can call methods on that instance that automatically pass the instance itself as the first parameter - the instance acts as the namespace for an instance method.
If you're using a class method or a static method, then the namespace is almost always going to be the class they're attached to. If you don't specify a namespace, then python assumes that whatever function you're trying to call is in the global namespace, and if it isn't, then you get a NameError.
In this case, the following should work for you:
class MyAbstract(ABC):
def get_current():
print("current")
def get_state():
MyAbstract.get_current()
#abstractmethod
def get_time():
pass
You can just imagine that you have a little invisible #staticmethod decorator hanging above get_current() that marks it as such. The problem with this is that now you don't get to change the behavior of get_current() in subclasses to affect change in get_state(). The solution to this is to make get_state() a class method:
#classmethod
def get_state(cls):
cls.get_current()
Calling a static method uses identical syntax to calling a class method (in both cases you would do MyAbstract.get_state(), but the latter passes the class you're calling it on as the first argument. You can then use this class as a namespace to find the method get_current() for whatever subclass has most recently defined it, which is how you implement polymorphism with method that would otherwise be static.

What is the purpose of using instance of a class as a super/base class?

What is the purpose of subclassing an instance of a class in Python? Here's an example:
class A:
def __init__(*args): print(args)
base = A()
class Test(base): pass
This code works properly under Python, but base is an instance of class A (1) Why do we need to subclass an instance of a class? Is it related to metaclasses?
From this question:
What happens when you inherent from a module instead of a class in Python?
I understand that Test(base) will become type(base).__init__, (2) does this happen at definition time, when the class is defined? (3) How does Python know/decide that base is an instance of a class? Is it becuase type(base) doesn't return type?
Python actually uses type(base)(classname, bases, body) to produce the class object. This is the normal metaclass invocation (unless the class specifies a specific metaclass directly).
For an instance (or a module, which is basically an instance too), that means the class __new__ static method is called to produce a new instance, and on that new instance __init__ is called. So for your class Test(base): pass syntax, you are essentially creating a new instance of A, when Python executes the class statement.
This isn't really 'definition time'; there is no such phase in Python code. Python loads the bytecode for a module and executes it when it is imported for the first time. Class statements at the top of the module (so not inside functions) are executed at that time. It is at that time then that the type(base)(...) call is executed, yes.
Python doesn't 'know' or 'decide' anything about the base class. Python's philosophy is to trust the developer that writes code in it. The assumption is that you know what you are doing, and the base classes are just treated as if they'll respond correctly. Since type(base)(....) didn't raise an exception, Python just continued.
You can use anything that's callable as a metaclass, really.

how do you return a property and save it as a global variable? (python)

here is my code:
def createProp(fget, fset, fdel):
class prop(object):
get=property(fget,fset,fdel)
return prop().get
x=createProp(getter,setter,deleter)
what I would like to do is have it return a property, so that I can make the variable x a property, but I can't figure out how to make a function like this. what it is doing instead is returning the value of the property, not the property itself.
python 2.6
createProp = property
Properties are perfectly ordinary objects. property is just another class. You can create an instance of it at runtime, in whatever context you want (no need for a class), pass them around, etc. And yes, you could (pointlessly) create one in a local class and then fetch it from there. But as the whole point of properties is overriding attribute access on instance, you'd have to fetch it from the class: return prop.get.
However, as property works its magic by means of the descriptor protocol, and descriptors have to be in a class to work. You can't have a global (or local) variable that's a property -- well, you can, but using it would just give you the descriptor object, not run fget, and assignment wouldn't trigger fset. You cannot do anything like that, and you shouldn't.

Why does "self" outside a function's parameters give a "not defined" error?

Look at this code:
class MyClass():
# Why does this give me "NameError: name 'self' is not defined":
mySelf = self
# But this does not?
def myFunction(self):
mySelf2 = self
Basically I want a way for a class to refer to itself without needing to name itself specifically, hence I want self to work for the class, not just methods/functions. How can I achieve this?
EDIT: The point of this is that I'm trying to refer to the class name from inside the class itself with something like self.class._name_ so that the class name isn't hardcoded anywhere in the class's code, and thus it's easier to re-use the code.
EDIT 2: From what I've learned from the answers below, what I'm trying to do is impossible. I'll have to find a different way. Mission abandoned.
EDIT 3: Here is specifically what I'm trying to do:
class simpleObject(object):
def __init__(self, request):
self.request = request
#view_defaults(renderer='string')
class Test(simpleObject):
# this line throws an error because of self
myClassName = self.__class__.__name__
#view_config(route_name=myClassName)
def activateTheView(self):
db = self.request.db
foo = 'bar'
return foo
Note that self is not defined at the time when you want the class to refer to itself for the assignment to work. This is because (in addition to being named arbitrarily), self refers to instances and not classes. At the time that the suspect line of code attempts to run, there is as of yet no class for it to refer to. Not that it would refer to the class if there was.
In a method, you can always use type(self). That will get the subclass of MyClass that created the current instance. If you want to hard-code to MyClass, that name will be available in the global scope of the methods. This will allow you to do everything that your example would allow if it actually worked. E.g, you can just do MyClass.some_attribute inside your methods.
You probably want to modify the class attributes after class creation. This can be done with decorators or on an ad-hoc basis. Metaclasses may be a better fit. Without knowing what you actually want to do though, it's impossible to say.
UPDATE:
Here's some code to do what you want. It uses a metaclass AutoViewConfigMeta and a new decorator to mark the methods that you want view_config applied to. I spoofed the view_config decorator. It prints out the class name when it's called though to prove that it has access to it. The metaclass __new__ just loops through the class dictionary and looks for methods that were marked by the auto_view_config decorator. It cleans off the mark and applies the view_config decorator with the appropriate class name.
Here's the code.
# This just spoofs the view_config decorator.
def view_config(route=''):
def dec(f):
def wrapper(*args, **kwargs):
print "route={0}".format(route)
return f(*args, **kwargs)
return wrapper
return dec
# Apply this decorator to methods for which you want to call view_config with
# the class name. It will tag them. The metaclass will apply view_config once it
# has the class name.
def auto_view_config(f):
f.auto_view_config = True
return f
class AutoViewConfigMeta(type):
def __new__(mcls, name, bases, dict_):
#This is called during class creation. _dict is the namespace of the class and
# name is it's name. So the idea is to pull out the methods that need
# view_config applied to them and manually apply them with the class name.
# We'll recognize them because they will have the auto_view_config attribute
# set on them by the `auto_view_config` decorator. Then use type to create
# the class and return it.
for item in dict_:
if hasattr(dict_[item], 'auto_view_config'):
method = dict_[item]
del method.auto_view_config # Clean up after ourselves.
# The next line is the manual form of applying a decorator.
dict_[item] = view_config(route=name)(method)
# Call out to type to actually create the class with the modified dict.
return type.__new__(mcls, name, bases, dict_)
class simpleObject(object):
__metaclass__ = AutoViewConfigMeta
class Test(simpleObject):
#auto_view_config
def activateTheView(self):
foo = 'bar'
print foo
if __name__=='__main__':
t = Test()
t.activateTheView()
Let me know if you have any questions.
Python has an "explict is better than implicit" design philosophy.
Many languages have an implicit pointer or variable in the scope of a method that (e.g. this in C++) that refers to the object through which the method was invoked. Python does not have this. Here, all bound methods will have an extra first argument that is the object through which the method was invoked. You can call it anything you want (self is not a keyword like this in C++). The name self is convention rather than a syntactic rule.
Your method myFunction defines the variable self as a parameter so it works. There's no such variable at the class level so it's erroring out.
So much for the explanation. I'm not aware of a straightforward way for you to do what you want and I've never seen such requirement in Python. Can you detail why you want to do such a thing? Perhaps there's an assumption that you're making which can be handled in another way using Python.
self is just a name, your self in this case is a class variable and not this for the object using which it is called,
self is treated as a normal variable and it is not defined, where as the self in the function comes from the object used for calling.
you want to treat the object reference in self as a class variable which is not possible.
self isn't a keyword, it's just a convention. The methods are attributes of the class object (not the instance), but they receive the instance as their first argument. You could rename the argument to xyzzy if you wanted and it would still work the same way.
But (as should be obvious) you can't refer to a method argument outside the body of the method. Inside a class block but outside of any method, self is undefined. And the concept wouldn't even make sense -- at the time the class block is being evaluated, no instance of the class can possibly exist yet.
Because the name self is explicitly defined as part of the arguments to myFunction. The first argument to a method is the instance that the method was called on; in the class body, there isn't an "instance we're dealing with", because the class body deals with every possible instance of the class (including ones that don't necessarily exist yet) - so, there isn't a particular object that could be called self.
If you want to refer to the class itself, rather than some instance of it, this is spelled self.__class__ (or, for new-style classes in Py2 and all classes in Py3, type(self)) anywhere self exists. If you want to be able to deal with this in situations where self doesn't exist, then you may want to look at class methods which aren't associated with any particular instance, and so take the class itself in place of self. If you really need to do this in the class body (and, you probably don't), you'll just have to call it by name.
You can't refer to the class itself within the class body because the class doesn't exist at the time that the class body is executed. (If the previous sentence is confusing, reading up about metaclasses will either clear this up or make you more confused.)
Within an instance method, you can refer to the class of the instance with self.__class__, but be careful here. This will be the instance's actual class, which through the power of inheritance might not be the class in which the method was defined.
Within a class method, the class is passed in as the first argument, much like instances are the first argument to instance methods:
class MyClass(object):
#classmethod
def foo(cls):
print cls.__name__
MyClass.foo() # Should print "MyClass"
As with instance methods, the actual class might differ due to inheritance.
class OtherClass(MyClass):
pass
OtherClass.foo() # Should print "OtherClass"
If you really need to refer to MyClass within a method of MyClass, you're pretty much going to have to refer to it as MyClass unless you use magic. This sort of magic is more trouble than it is worth.

Categories

Resources