Get variable name from argument/parameter in class function - python

I try to get the name of the variable, which I passed to a function.
class A():
def __init__(self):
self.a = 1
class B():
def __init__(self):
self.b = A()
self.c = A()
def doSomething(self, hello):
print(hello)
B().doSomething(B().b)
<__main__.A object at 0x7f67571a3d68>
What I want is that I can identify in the function B().doSomething(), that the variable is b. Is this possible? One restriction is that in the function B().doSomething() only instance variables of B are passed.
For example in peewee (https://github.com/coleifer/peewee), a MySQL ORM in python, they build expressions for filtering like:
B.select().where(B.b == True)
And somehow they are able to identify, that b is passed. Because otherwise the query can not be build properly.
I know they are using static variables in the class, is this maybe the trick?
Thanks for helping! :)

Going by your B().doSomething(B().b) example call I'm going to assume you're attempting to determine if the variable hello is equivalent to the variable b declared on the class B object.
In which case, all you need to do is call the self reference. self refers to the instance of the object that you're working with and every method defined within a class automatically gets reference to the object's self as a method attribute.
Thus, to determine if the the object b variable is equal to the hello parameter all you need to do is if self.b == hello: #do code

B().b is not an instance variable of B; rather, it is an instance variable of A. In your constructor in B, you may have meant self.a to be an instance of B or self.a to be an instance of B. If this is your general idea, you can implement a boolean overloading method to destinguish between the two. In the case of your code, it may be best to create a third class, C, to check what class an attribute that is passed to doSomething belongs to:
class A():
def __init__(self):
self.a = 1
def __bool__(self):
return True
class B():
def __init__(self):
self.b = 1
def __bool__(self):
return False
class C():
def __init__(self):
self.a = A()
self.b = B()
def doSomething(self, hello):
if not hello:
print("instance of a got passed")
else:
print("instance of b got passed")
C().doSomething(C().b)
Output:
instance of b got passed

Related

Check if an attribute is reassigned in derived class

In Python 2.7, I have the following example classes defined:
class A:
def __init__(self):
self.a = 1
self.b = 3
class B(A):
def __init__(self):
A.__init__(self)
self.a = 1
obj_b = B()
print(vars(obj_b))
Object obj_b now has both a and b. Although a has the same value as in class A, it's been reassigned in class B.
Is there any way to tell if a is reassigned in class B?
yeah, I see what you mean, thanks, so is there any way to check if such reassignment happened in class B's constructor?
Answering a question from the comments, this can certainly be done. It's not foolproof, in the sense that a programmer can go out of their way to cheat your system, but they have to do so on purpose.
We just need to make a a property.
class A:
def __init__(self):
self._a = 1
self.was_a_changed = False
#property
def a(self):
return self._a
#a.setter
def a(self, x):
self._a = x
self.was_a_changed = True
class B(A):
def __init__(self):
self.a = 1
class C(A):
pass
obj_a = A()
obj_b = B()
obj_c = C()
print(obj_a.was_a_changed) # False
print(obj_b.was_a_changed) # True
print(obj_c.was_a_changed) # False
Now a isn't a real value; it's a property which is backed by the actual value _a. But if a subclass reassigns a, it'll make a note so that we can check whether it's been touched later.
If someone wants to cheat your system, they can always assign directly to self._a rather than self.a, but that would be unidiomatic Python to assign to a private you don't own anyway.
If a is a class attribute, rather than an instance attribute, this question would make more sense. An instance of A (possibly a subclass) could compare self.__class__.a against A.a. As is you could potentially compare self.a against A().a, but there's no way to distinguish between changes made during initialization and changes made at any other point.

New method to a class outside of the class definition

In Python, does anyone know of a nicer way of overriding a method of instantiated object that would give the function access to the class instance (self) and all its methods/properties?
The one below works, but somehow I do not like how use the global scope to pass object a to the new_f.
class A(object):
def __init__(self):
self.b = 10
def f(self):
return 2 + self.b
def g(self):
print(self.f())
a = A()
# simple override case
a.f = lambda: 10
a.g()
# now I want to have access to property b of the object a
# but it also could be a method of object the object a
def new_f():
self = a
return 10+self.b
a.f = new_f
a.g()
One possible solution depending on your use case would be to define the function with self as an argument like def new_f(self) and then define A.f = new_f before initializing object a.

Access class which object is being called from within method belonging to object

I wonder if there is a way in Python to access the class which the object which the method belongs to is being called from. For example:
class A:
def __init__(self):
self.b = B()
def foo(self):
print('A')
class B:
def bar(self):
<something here>.foo()
a = A()
a.b.bar()
Basically I would like B's method bar to invoke A's method foo. And if b was an attribute of some other class C, to invoke C's version of foo instead.
You could add a reference to the class which instantiates B:
class A:
def __init__(self):
# pass self while instantiating B
self.b = B(self)
def foo(self):
print('A')
class B:
def __init__(self, rel_obj):
self.rel_obj = rel_obj
def bar(self):
self.rel_obj.foo() # access foo() using self.rel_obj
Similarly, you could pass an object of class C to invoke C's version of foo method.

Why I can't instantiate a instance in the same module?

Suppose my module is myclass.py, and here is the code:
#!/usr/bin/env python
# coding=utf-8
class A(object):
b = B()
def __init__(self):
pass
class B(object):
pass
and import it
In [1]: import myclass
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-1-e891426834ac> in <module>()
----> 1 import myclass
/home/python/myclass.py in <module>()
2 # coding=utf-8
3
----> 4 class A(object):
5 b = B()
6 def __init__(self):
/home/python/myclass.py in A()
3
4 class A(object):
----> 5 b = B()
6 def __init__(self):
7 pass
NameError: name 'B' is not defined
I know that if I define the class B above the class A, it is ok, there is no error. But, I don't want do that, are there any other methods to solve this. And I know that in C, there is function declaration.Thank you!
The class definition is a statement. When statement AA is executed, The statement of BB is not executed yet. Therefore, There is no class B yet and you get NameError: name 'B' is not defined
class A(object):
b = B() # <== AA
def __init__(self):
pass
class B(object): # <== BB
pass
To fix it:
You can change the order of classes:
class B(object):
pass
class A(object):
b = B()
def __init__(self):
pass
You can move the statement which use the class B to classmethod and call it after the the defintion of class B:
class A(object):
#classmethod
def init(cls):
cls.b = B()
def __init__(self):
pass
class B(object):
pass
A.init()
It should work if you do it like so:
class A(object):
def __init__(self):
self.b = B()
class B(object):
pass
EDIT: You can do it like this if you want to write all the definitions of the class after you have written class A.
class B:
pass
class A(object):
b = B()
def __init__(self):
pass
class B(object):
def __init__(self):
pass
EDIT 2: Ignore the above solution, it doesn't work.
Is there any good reason to do what you are doing? In general this is quite dangerous pattern in Python.
In your case
class A(object):
b = B()
def __init__(self):
pass
You are binding an instance of B to the class A, which means that every instance of class A will share the same instance of class B. It's a case you must then handle properly.
In general you don't want this, If you want each instance of A to be related to an instance of B, you must make the assignment inside __init__
class A(object):
def __init__(self):
self.b = B()
In these case it doesn't meter where class B is defined, since it's instantiated at run time.
Again beware that the semantic is very different in the two cases (if you know Java, the former is more like defining a static attribute).
About:
And I know that in C, there is function declaration
You shouldn't make too much parallels with a language like C, which is very different on many aspects, most important: it's a compiled language, that means that you code is parsed in it whole before being translated to machine language, that's why you can make function declaration and have your namespace populated regardless of the order you define things.
Python is an interpreted language, which means basically that each statement is translated when it's called and a class declaration is called when the module is imported.
So to recap: if you really need a class bound instance, you have to declare class B before class A, else you must instantiate B inside __init__, then you can declare B wherever you want (since it's called at runtime).

Calling a method's variablename from class A into Class B

I have been searching an answer to my question but could not hit the related answer.
Basically i am trying to call a variable from a Class A thats actually GUI to another Class B my code goes like this:
class CLASSA(wx.Frame):
def Method(self):
self.Var = anyvalue
import CLASSA
class CLASSB():
def __init__(self):
self.Var = CLASSA().Method.Var
i have tried as above but its not working out. Isn't it possible to carry out as mentioned ?
At the very least, you need to actually call CLASSA.Method first:
class CLASSB():
def __init__(self):
self.Var = CLASSA().Method().Var
in order for the Var attribute of the CLASSA object to be initialized.
You do not give enough detail to know if Method is necessary. You could, for instance, simply initialize Var in CLASSA.__init__.
# With recommended capitalization
class A(wx.Frame):
def __init__(self):
self.var = any value
class B(object):
def __init__(self):
sef.var = A().var
It's also possible that B should be a subclass of A, in which case B simply inherits var from A:
>>> class B(A):
... pass
>>> print B().var
anyvalue

Categories