Say I have this code:
class hello_world():
def define_hello(self):
self.hello = "hello"
def say_hello(self):
print self.hello
class change_to_goodbye():
def __init__(self):
self.helloWorld = hello_world()
def hello_to_goodbye(self):
self.helloWorld.hello = "goodbye"
class other_class():
def __init__(self):
self.helloWorld = hello_world()
self.changeToGoodbye = change_to_goodbye()
self.helloWorld.define_hello()
self.changeToGoodbye.hello_to_goodbye()
self.helloWorld.say_hello()
oc = other_class()
Class hello_world has two methods, one that defines the variable hello and one that prints it. On the other hand, class change_to_goodbye tries to access the variable hello in class hello_world and changes it to goodbye. Class other_class should set the variable hello to "hello", change it to "goodbye", and print it on the screen.
I expected the output to be "goodbye" but I got "hello". Why isn't change_to_goodbye changing the variable of hello_world?
This is because your change_to_goodbye class stores its own hello_world object inside it. The hello_world object in changeToGoodbye is not the same as the hello_world object helloWorld. So in other_class when you do self.changeToGoodbye.hello_to_goodbye(), your helloWorld variable isn't being altered at all. What's being altered is changeToGoodbye's helloWorld object.
So: self.changeToGoodbye.helloWorld.say_hello() would return goodbye.
So to summarize:
class other_class():
def __init__(self):
self.helloWorld = hello_world()
self.changeToGoodbye = change_to_goodbye() #contains a different hello_world object
self.helloWorld.define_hello()
self.changeToGoodbye.hello_to_goodbye() #changes the hello_world object inside of changeToGoodbye
self.helloWorld.say_hello() #the unaltered helloWorld object
if you wanted to change the output of helloWorld, you could change the change_to_goodbye class's constructor so that its hello_world object is the one you just created.
class change_to_goodbye():
def __init__(self, hw):
self.helloWorld = hw
#other code
You are not changing class variable, you are changing instance variable.
By self.helloWorld = hello_world() you defines an hello_world instance let's called it A, and self.changeToGoodbye = change_to_goodbye() you defines an change_to_goodbye instance B which has an hello_world instance C.
Then self.helloWorld.define_hello() set A's variable as hello and self.changeToGoodbye.hello_to_goodbye() set C's variable as goodbye.
At last self.helloWorld.say_hello() will print A's variable, and you will get hello.
Related
I want to access an attribute outside a class, but even after googling I don't see any similar solution for this particular problem.
class test():
def __init__(self) -> None:
pass
def testpy(self):
self.x = 'Hello world'
value = test().testpy.x
print(value)
>> AttributeError: 'function' object has no attribute 'x'
I think you are confused with what an attribute is.
In your code X is a local variable in the member function testpy. X exists only in that function, and is deleted upon function exit.
If you want a member, write self.x = 'Hello world'. This will create and store a data member called x. Additionally, when you write test().testpy().x you are calling the member function testpy() and are then attempting to call .x on the return result, which will obviously break.
I think you're confusing local scope, with class attributes, and global scope.
You can achieve your result in one of three ways:
Creating a class attribute to access
Using the return keyword to return local values
Using the global keyworld to create a globally scoped variable. Highly not recommended
class test:
def __init__(self) -> None:
self.x = "Hello world"
pass
def testpy(self):
self.x = "Hello world"
x = "Hello world"
global Y
Y = "Hello world - global"
return x
object = test()
value_via_objects_attribute = object.x
value_via_objects_method = object.testpy()
value_via_global = Y
print(value_via_objects_attribute)
print(value_via_objects_method)
print(value_via_global)
In your code, x is a local variable inside a function, not a class attribute. You can return that variable:
class test():
def __init__(self) -> None:
pass
def testpy(self):
x = 'Hello world'
return x
value = test().testpy()
print(value)
Please go through python class tutorial once more.
testpy is a function of class Test, it returns None in the above code. x is an attibute of class Test not function 'testpy'
class Test():
def __init__(self):
pass
def testpy(self):
self.x = 'Hello world'
t = Test()
t.testpy()
value = t.x
print(value)
I think you are confusing your testpy() function with your constructor - the init method. In python, you can initialize a new object by calling the class as if it were a function - ex, "value = test()". When you call this function, the init method gets called, and returns a new object (self). So to declare an attribute on self, in the init function (your constructor), you simply write "self.x = "Hello World".
The full solution to your problem is below.
class test():
def __init__(self):
self.x = 'Hello World'
value = test()
print(value.x)
I want to create a python library and part of the function of this library involves creating a class instance with some user defined variables. How do I let the user write their own conditionals for the class instance in said instance's method? For example, say I have an instance of the following class:
class Test:
def __init__(self, some_value):
self.some_value = some_value
def func(self):
pass
instance = Test(4)
How do I let a user change what instance.func() does (how can I let a user access the object's variables?
You could pass a reference to the user's function to init For example:
class Test:
def __init__(self, user_function):
self._function = user_function
def func(self):
return self._function()
def ufunc_1():
return 'Hello world!'
def ufunc_2():
return 'Goodbye cruel world'
t_1 = Test(ufunc_1)
t_2 = Test(ufunc_2)
print(t_1.func())
print(t_2.func())
In this way, the reference to the user function is stored in an instance variable.
Output:
Hello world!
Goodbye cruel world
I'd like to define a class inside a function (for testing purpose) and put a value into
a function variable:
def foo():
myvar = None
class myclass:
def run(self):
myvar = 5
mm = myclass()
mm.run()
print(myvar)
The above prints None
Is there any way other than global to make the myvar variable accessible from the class? The correct answer would print 5
It's not possible to assign a value to a variable outside the current scope without global. If you need to persist the value within the class you can define class variables instead. Example:
def foo():
class Class:
var_to_change = None
def run (self):
self.var_to_change = 5
print (Class.var_to_change)
instance = Class()
instance.run()
print (Class.var_to_change)
I haven't tested the above code but it should work in theory.
I am trying to call a class variable within a staticmethod, but when I called I am getting an error "hello" is not defined. any advise ?
class hello:
random1 = []
#staticmethod
def sub(x):
hello.random1.append(x -1)
sub.__func__(2)
if __name__ == "__main__":
print(hello.random1)
hello doesn't exist as a global name until you dedent out of the class definition (at which point the class is created and assigned to the global name hello). Change the code to:
class hello:
random1 = []
#staticmethod
def sub(x):
hello.random1.append(x -1)
hello.sub(2)
so sub is invoked after hello exists, and it will work.
Let's say, I have a function named my_function and I'm passing an object as its parameter in the following way:
my_obj = MyClass()
my_function(my_obj)
Is there a way using which I can print the name of the function inside a method of MyClass?
Let's say that MyClass has a method called display_info inside it and it prints the name of the function in where the object of MyClass is passed.
An example would be:
class MyClass:
def print_log(self):
# some code
def random_method_1():
pass
def random_method_2():
def my_function(param1, some_name, some_number):
# some code
# Instantiating MyClass
my_object = MyClass()
# Calling my_function
my_function(my_object, "John Doe", 38478347)
my_object.print_log()
# Above line of code should be able to print "my_function"
Design your program better
If you need this systematically you might want a better designed program, e.g. one that injects the name of the parent or calling entity into e.g. my_obj.display_info(caller='something')
class MyClass:
def display_info(self, caller):
print caller
def my_function(my_obj):
my_obj.display_info(caller='my_function')
The above allows that param to be injected by each caller.
Or keep a reference to the caller in MyClass.caller at init time if possible, or set it on the spot as needed e.g.
# pseudo code
class MyClass:
def __init__(self, caller):
self.caller = caller
def display_info(self):
print self.caller
my_obj = MyClass(caller='caller')
my_obj.display_info()
my_obj.caller = 'new_caller'
my_obj.display_info()
The inspect hack to avoid
The inspect module provides several useful functions to help get
information about live objects such as modules, classes, methods,
functions, tracebacks, frame objects, and code objects.
Yes usng inspect. When you call inspect.stack() you get a record of frame objects. So we use stack()[1] to get the previous frame, which is a tuple where the third element is the name of the caller (my_function). Hence stack()[1][3].
>>> import inspect
>>> class MyClass():
... def display_info(self):
... print inspect.stack()[1][3]
...
>>> def my_function(my_obj):
... my_obj.display_info()
...
>>> my_obj = MyClass()
>>> my_function(my_obj)
my_function # <--- The result you wanted
>>>
>>> def another_fn(my_obj):
... my_obj.display_info()
...
>>> another_fn(my_obj)
another_fn
This provides the result you want (prints the name of the calling function)