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()
Related
I have some code like:
class Pump:
def __init__(self):
print("init")
def getPumps(self):
pass
p = Pump.getPumps()
print(p)
But I get an error like:
Traceback (most recent call last):
File "C:\Users\Dom\Desktop\test\test.py", line 7, in <module>
p = Pump.getPumps()
TypeError: getPumps() missing 1 required positional argument: 'self'
Why doesn't __init__ seem to be called, and what does this exception mean? My understanding is that self is passed to the constructor and methods automatically. What am I doing wrong here?
To use the class, first create an instance, like so:
p = Pump()
p.getPumps()
A full example:
>>> class TestClass:
... def __init__(self):
... print("in init")
... def testFunc(self):
... print("in Test Func")
...
>>> testInstance = TestClass()
in init
>>> testInstance.testFunc()
in Test Func
You need to initialize it first:
p = Pump().getPumps()
Works and is simpler than every other solution I see here :
Pump().getPumps()
This is great if you don't need to reuse a class instance. Tested on Python 3.7.3.
The self keyword in Python is analogous to this keyword in C++ / Java / C#.
In Python 2 it is done implicitly by the compiler (yes Python does compilation internally).
It's just that in Python 3 you need to mention it explicitly in the constructor and member functions. example:
class Pump():
# member variable
# account_holder
# balance_amount
# constructor
def __init__(self,ah,bal):
self.account_holder = ah
self.balance_amount = bal
def getPumps(self):
print("The details of your account are:"+self.account_number + self.balance_amount)
# object = class(*passing values to constructor*)
p = Pump("Tahir",12000)
p.getPumps()
Adding a #classmethod decorator to the method allows for calling it like Pump.getPumps().
A class method receives the class as the implicit first argument, just like an instance method receives the instance.
class Pump:
def __init__(self):
print("init")
#classmethod
def getPumps(cls):
pass
You can also get this error by prematurely taking PyCharm's advice to annotate a method #staticmethod. Remove the annotation.
If skipping parentheses for the object declaration (typo), then exactly this error occurs.
# WRONG! will result in TypeError: getPumps() missing 1 required positional argument: 'self'
p = Pump
p.getPumps()
Do not forget the parentheses for the Pump object
# CORRECT!
p = Pump()
p.getPumps()
I got the same error below:
TypeError: test() missing 1 required positional argument: 'self'
When an instance method had self, then I called it directly by class name as shown below:
class Person:
def test(self): # <- With "self"
print("Test")
Person.test() # Here
And, when a static method had self, then I called it by object or directly by class name as shown below:
class Person:
#staticmethod
def test(self): # <- With "self"
print("Test")
obj = Person()
obj.test() # Here
# Or
Person.test() # Here
So, I called the instance method with object as shown below:
class Person:
def test(self): # <- With "self"
print("Test")
obj = Person()
obj.test() # Here
And, I removed self from the static method as shown below:
class Person:
#staticmethod
def test(): # <- "self" removed
print("Test")
obj = Person()
obj.test() # Here
# Or
Person.test() # Here
Then, the error was solved:
Test
In detail, I explain about instance method in my answer for What is an "instance method" in Python? and also explain about #staticmethod and #classmethod in my answer for #classmethod vs #staticmethod in Python.
I am trying to write a function taking a string as an argument and using this argument as a class object.
Note that my explanantion might be strangely formulated sice I could not find an answer online. The MWE below should clarify what I mean, the problematic line is indicated.
Edit: in the MWE, "print" is an example. I need to be able to call the object to update it, print it or, in the case of a list, append to it. I need access to the object itself, not the value of the object.
MWE
# Create a class
class myClass():
def __init__(self):
self.one = "Test"
self.two = "Plop"
# Define function
def myFunction (parameter):
print(myObject.parameter)##### This line is currently not possible.
# Use class
myObject = myClass()
# Use function
myFunction("one")
I am not trying to append a new object to the class, only to call an existing object.
Is this even possible?
Looks like you need the built-in function called getattr
my_object = myClass()
def my_function(parameter):
print(getattr(my_object, parameter, None))
also this is not the best practice to call objects from outer scope like that. i'd suggest to use dict magic methods:
class MyClass:
def __init__(self):
self.one = "Test"
self.two = "Plop"
def __getitem__(self, parameter):
return getattr(self, parameter, None)
def __setitem__(self, parameter, value):
return setattr(self, parameter, value)
my_obj = MyClass()
parameter = "x"
print(my_obj[parameter])
my_obj[parameter] = "test"
print(my_obj.x)
You need to use getarttr():
# Create a class
class myClass():
def __init__(self):
self.one = "Test"
self.two = "Plop"
# Use class
myObject = myClass()
# Define function
def myFunction(parameter):
print(getattr(myObject, parameter))##### This line is currently possible.
# Use function
myFunction("one")
I have some code like:
class Pump:
def __init__(self):
print("init")
def getPumps(self):
pass
p = Pump.getPumps()
print(p)
But I get an error like:
Traceback (most recent call last):
File "C:\Users\Dom\Desktop\test\test.py", line 7, in <module>
p = Pump.getPumps()
TypeError: getPumps() missing 1 required positional argument: 'self'
Why doesn't __init__ seem to be called, and what does this exception mean? My understanding is that self is passed to the constructor and methods automatically. What am I doing wrong here?
To use the class, first create an instance, like so:
p = Pump()
p.getPumps()
A full example:
>>> class TestClass:
... def __init__(self):
... print("in init")
... def testFunc(self):
... print("in Test Func")
...
>>> testInstance = TestClass()
in init
>>> testInstance.testFunc()
in Test Func
You need to initialize it first:
p = Pump().getPumps()
Works and is simpler than every other solution I see here :
Pump().getPumps()
This is great if you don't need to reuse a class instance. Tested on Python 3.7.3.
The self keyword in Python is analogous to this keyword in C++ / Java / C#.
In Python 2 it is done implicitly by the compiler (yes Python does compilation internally).
It's just that in Python 3 you need to mention it explicitly in the constructor and member functions. example:
class Pump():
# member variable
# account_holder
# balance_amount
# constructor
def __init__(self,ah,bal):
self.account_holder = ah
self.balance_amount = bal
def getPumps(self):
print("The details of your account are:"+self.account_number + self.balance_amount)
# object = class(*passing values to constructor*)
p = Pump("Tahir",12000)
p.getPumps()
Adding a #classmethod decorator to the method allows for calling it like Pump.getPumps().
A class method receives the class as the implicit first argument, just like an instance method receives the instance.
class Pump:
def __init__(self):
print("init")
#classmethod
def getPumps(cls):
pass
You can also get this error by prematurely taking PyCharm's advice to annotate a method #staticmethod. Remove the annotation.
If skipping parentheses for the object declaration (typo), then exactly this error occurs.
# WRONG! will result in TypeError: getPumps() missing 1 required positional argument: 'self'
p = Pump
p.getPumps()
Do not forget the parentheses for the Pump object
# CORRECT!
p = Pump()
p.getPumps()
I got the same error below:
TypeError: test() missing 1 required positional argument: 'self'
When an instance method had self, then I called it directly by class name as shown below:
class Person:
def test(self): # <- With "self"
print("Test")
Person.test() # Here
And, when a static method had self, then I called it by object or directly by class name as shown below:
class Person:
#staticmethod
def test(self): # <- With "self"
print("Test")
obj = Person()
obj.test() # Here
# Or
Person.test() # Here
So, I called the instance method with object as shown below:
class Person:
def test(self): # <- With "self"
print("Test")
obj = Person()
obj.test() # Here
And, I removed self from the static method as shown below:
class Person:
#staticmethod
def test(): # <- "self" removed
print("Test")
obj = Person()
obj.test() # Here
# Or
Person.test() # Here
Then, the error was solved:
Test
In detail, I explain about instance method in my answer for What is an "instance method" in Python? and also explain about #staticmethod and #classmethod in my answer for #classmethod vs #staticmethod in Python.
I have a setup that looks as following:
def docstring_formatter(func):
func.__doc__ = func.__doc__.format(class_name=func.__self__.__class__.__name__) #this does not work
return func
class A:
#docstring_formatter
def my_function(self):
"""I am a function of class {class_name}"""
print("test")
class B(A):
pass
docstring = getattr(B.my_function, "__doc__")
>>> AttributeError: 'function' object has no attribute '__self__'
I would like to access the actual class name that the instance of my_function belongs to. Since I am not instantiating the class I when I am using the help() function, the __self__ property is not instantiated yet and I can also not make use of the functools.wraps function. I would like to find a way to also extract the string B or B.my_function when being passed a my_function object that could either belong to A() or B().
Given the code:
class A:
def my_function(self):
print("test")
class B(A):
pass
b = B()
The my_function object has a self binding to the object you took it from, which is a B, so you can do:
>>> b.my_function.__name__
'my_function'
>>> b.my_function.__self__.__class__.__name__
'B'
I have a function which returns a class:
def my_function():
# some logic
class AClass:
def __init__(self, argument):
init()
return AClass
And when I call this function, it returns a class, not an object of that class, right?
Value = my_function()
My question is how can I create an object from that class AClass?
Thank you.
my_class = my_function()
my_obj = my_class(arg)
Since the method returns a reference to a type you can simply use whatever constructor that is defined for the class directly on the return value.
Take this class for example:
class A:
def __init_(self, n = 0):
self.__n = n
Lets see what happens when reference the type directly when running the interpreter interactively:
>>> A
<class `__main__.A`>
Now lets return the type in a method:
>>> def f():
>>> return A
>>> f()
<class `__main__.A`>
Since the value of referencing the class directly and when returned from a method is the same, you can use that returned value the same you would normally. Therefore a = A() is the same as a = f()(). Even if the class takes parameter you can still reference it directly: a = f()(n = 10)