Why python class definition can refer to a concrete class instance name? - python

For example:
class abc:
def show(self):
print(self)
print(a)
a = abc()
a.show()
Here a is an instance of the class, which can be directly referred to in the method by its name, in addition to by the first argument self.
Why is this allowed?

Related

Get class name at class level

Is there a way to get the name of a class at class level in Python?
Minimum working example:
class TestClass:
print("We are now in the class {} at class level".format(WHAT SHOULD I PUT HERE?)) # Should return "We are now in the class TestClass at class level"
pass
Here's how you can find out:
class TestClass:
print(locals())
This prints:
{'__module__': '__main__', '__qualname__': 'TestClass'}
So you can use __qualname__, i.e.
class TestClass:
print("We are now in the class {} at class level".format(__qualname__))
This works :
class Test :
CLASSNAME = locals()['__qualname__']
Use the CLASSNAME variable anywhere in the class or outside.
For defined classes only: Use type(self).__name__ where .__name__ is a default attribute.
Refer to #Alex Hall's answer for using the class name before __init__ takes place, using locals().

How to call a function within a class with self

Suppose I have the following:
class myClass:
def foo(self):
# do something
How can I call myClass from inside the class without declaring an new myClass Object? i.e. I'd like something like
class myClass:
def foo(self):
# do something
if __name__ == '__main__':
# call foo
or without main:
class myClass:
def foo(self):
# do something
# call foo
Right now I keep getting either the error that self is not defined, or the error that foo expects 1 argument but 0 was provided.
You cannot. The function is part of the class, so to access it you must access the class first.
class myClass:
def foo(self):
# do something
myClass().foo()
If you just don't want to type myClass().foo() but only foo then you could just return the myClass() in a new function called foo():
def foo():
return myClass().foo()
You can use self in a class when calling from inside the class itself:
class myClass:
def __init__(self):
pass
def foo(self):
pass
def method2(self):
self.foo()
This does not create a new instance of myClass like calling myClass().foo() would, and you do not need to pass the same arguments that you may have passed in myClass.
Since foo() has a self parameter, that means it is an instance method, and therefore it is only callable from an instance of myClass.
If you want foo to be callable without an instance, use the #staticmethod decorator, and remove self from the parameter list.

How to find a abstract class instance and call an instance method based on the instance' attributes?

I want to call an instance method but the instance itself is unknown to me. The instance can be identified by it's attributes which I know, e.g. a unique name.
Here're my class definitions and instantiation:
from abc import ABCMeta
class MyAbstractClass():
__metaclass__ = ABCMeta
def do_something(self):
print(self.name)
class MyFirstClass(MyAbstractClass):
def __init__(self):
self.name = 'first'
class MySecondClass(MyAbstractClass):
def __init__(self):
self.name = 'second'
my_first_class_instance = MyFirstClass()
my_second_class_instance = MySecondClass()
What I want to achive is a look-up by name:
def myPrint('first'):
# should call my_first_class_instance.do_something()
def myPrint('second'):
# should call my_second_class_instance.do_something()
I looked into the built-in class methods but didn't find a way to manage the parametrization of the calls.
What's a good way of doing this?

Python static inheritance in class variable

In python, is there a way to get the class name in the "static constructor"? I would like to initialize a class variable using an inherited class method.
class A():
#classmethod
def _getInit(cls):
return 'Hello ' + cls.__name__
class B(A):
staticField = B._getInit()
NameError: name 'B' is not defined
The name B is not assigned to until the full class suite has been executed and a class object has been created. For the same reason, the __name__ attribute on the class is not set until the class object is created either.
You'd have to assign that attribute afterwards:
class A():
#classmethod
def _getInit(cls):
return 'Hello ' + cls.__name__
class B(A):
pass
B.staticField = B._getInit()
The alternative is to use a class decorator (which is passed the newly-created class object) or use a metaclass (which creates the class object in the first place and is given the name to use).

Refer to a class outside its method?

I need to deliver something like this in my program
class the_class_name(Parent):
the_attribute = self.parent_class_method()
#the parent class method will return a value
#but I cannot use self here since there's no self
How can I carry this out? Is there any other alternative that can do the job for me?
I have tried using __init__ like this:
def __init__(self):
Parent.__init__(self)
self.attribute = self.the_method()
But then I have problem creating the object, it won't receive any parameters that the Parent class normally receives anymore
Sounds like you are looking for __init__:
class TheClassName(Parent):
def __init__(self):
# Set attribute to the result of the parent method
self.attribute = super(TheClassName, self).the_method()
EDIT
If your parent class has parameters in it's own __init__ function, include them in the child class:
class Parent(object):
def __init__(self, foo, bar):
...
#classmethod
def the_method(cls):
...
class TheClassName(Parent):
def __init__(self, foo, bar):
super(TheClassName, self).__init__(foo, bar)
self.attribute = super(TheClassName, self).the_method()
I don't quite understand why you don't just call the parent method on your child object when you need the value though.
There is no self at that point of the creation of the subclass, nor is there an instance of the Parent class. That means the only Parent class methods you could call would have to be either static or class methods.
To demonstrate:
class Parent(object):
#staticmethod
def static_method():
return 42
#classmethod
def class_method(cls):
return 43
class TheClassName(Parent):
the_attribute = Parent.static_method()
another_attribute = Parent.class_method()
print(TheClassName.the_attribute) # -> 42
print(TheClassName.another_attribute) # -> 43
You must use class methods, declared with the #classmethod decorator, or a #staticmethod. The #classmethod decorator is preferable so that inheritance is handled correctly, i.e. the method is invoked on the derived class (a bit of a technicality, if you are still learning this).
class Alpha(object):
#classmethod
def method1(cls):
return 'method1 has been called on {}'.format(cls)
class Beta(Alpha):
def __init__(self):
self.myattr = Beta.method1()
print(Beta().myattr)
method1 has been called on class <'__main__.Beta'>
Use
super(ClassName, self).methodname(arg)
inside a method
def child_method(self, arg):
super(ClassName, self).methodname(arg)
You cannot use self outside a method.

Categories