How to Change a Class Instance's Method in Python? - python

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

Related

Is there a way to access an attribute outside a class?

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)

Python:Error calling class variable in a staticmethod

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.

Inheritance from a parent class without arguments

I have two classes. A vehicle class and a car class. My vehicle class does not have any attributes so I can call it without any arguments. Same for my car class. The car class is a sub class for vehicle class.
In my vehicle class I have a variable assigned a string with some text. How can my sub class car inheritance that variable?
Code:
class Vehicle(object):
def __init__(self):
self.__astring = 'Hello'
def get_string(self):
print self.__astring
class Car(Vehicle):
def __init__(self):
Vehicle.__init__(self)
# Here I need to make a working variable
self.__car_string = self.__astring
self.__car_string2 = ' Again'
self.__big_string = self.__car_string + self.__car_string2
# This method should print 'Hello Agan'
def get_car_string(self):
print self.__big_string
string1 = Vehicle()
string1.get_string() # This prints Hello
string2 = Car()
string2.get_car_string() # This should print Hello Again
When I run the code, I get:
AttributeError: 'Car' object has no attribute '_Car__astring'
I do understand why, but I do not know how to inherit that variable with the string.
The correct way to mark an attribute as private (meaning it should not be used directly outside of a method of that class, not that it cannot), is to prefix it with a single underscore.
A getter method should return the value, not print it. If you need to print the value, you can always print the return value of get_string; you cannot (easily) access a value that is directly printed by a method.
class Vehicle(object):
def __init__(self):
self._astring = 'Hello'
def get_a_string(self):
return self._astring
class Car(Vehicle):
def __init__(self):
Vehicle.__init__(self)
# Here I need to make a working variable
self._car_string = self.get_a_string()
self._car_string2 = ' Again'
self._big_string = self._car_string + self._car_string2
def get_car_string(self):
print self._big_string
The language itself will not stop you from accessing Vehicle._astring directly outside of the Vehicle class, but it should be considered a bug to do so.

Is there a python construct that is a dummy function?

Is there a python construct that corresponds to a function taking no argument, doing nothing and returning nothing ? Something similar to object None but that would be a function instead of an object ?
The context
I want to define a class where the constructor gets a function as an argument and references it to a class attribute. Upon instanciation, the user decides whether he/she wants that function to be an actual function which he/she defines him/herself or leave the default which is to call a dummy function which does nothing.
Here is what I have now :
def sayHello():
print("hello world !")
def doNothing():
pass
class myClass:
def __init__(self, myFunc):
self.doIt = myFunc
myInstance = myClass(sayHello)
myInstance.doIt()
myInstance = myClass(doNothing) # Works but requires defining function doNothing()
myInstance.doIt()
#myInstance = myClass(None) # Returns error "'NoneType' object is not callable"
myInstance.doIt()
How about lambdas?
myInstance = myClass(lambda:None)
Sure you can pass is as default to your __init__ function:
class myClass:
def __init__(self, myFunc = lambda:None):
self.doIt = myFunc
This should work:
class myClass:
def __init__(self, myFunc = lambda : None):
self.doIt = myFunc
myInstance = myClass()
I used the following:
a=lambda:None
a()
print a()
The latter line prints None.
This worked for me:
def none(function=True):
if function==True:
return None
else:
function()

Changing Variables in Class from Other Classes (Python)

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.

Categories

Resources