Python classes: optional argument - python

I want the user to be able to initiate a class by passing an argument to it, and if he doesn't pass it then it should be automatically created by the class. How is that usually done in Python? Example:
class MyClass(object):
def __init__(self, argument):
self.argm = argument
# logic here: if user does not pass argument
# run some function or do something
def create_argm(self):
self.argm = 'some_value'
object_example = MyClass()
print(object_example.argm) # will print 'some_value'
object_example = MyClass('some_other_value')
print(object_example) # will print 'some_other_value'
Edit : self.argm will be a python-docx Object so i'm unable to do def __init__(self, argument = Document() or am i?

if you cant create the value in the function definition, you can use a value that indicates nothing, luckily python has None so you can do something like:
class MyClass(object):
def __init__(self, argument=None):
if argument is None:
self.argm = self.create_argm()
else:
self.argm = argument
def create_argm(self):
return 'some_value'
if None Doesn't fit because you want that to be a valid value for argument without assuming it was left out you can always create a dummy value:
class MyNone:
pass
class MyClass(object):
def __init__(self, argument=MyNone):
if argument is MyNone:
self.argm = self.create_argm()
else:
self.argm = argument
def create_argm(self):
return 'some_value'

This is usually done with a default value assigned to a key word argument:
class MyClass(object):
def __init__(self, argument='default value'):
self.argm = argument
You have to pay special attention if you want this default value to be a mutable object; this may lead to unwanted behavior, as the object will be created only once, then mutated.

Related

Python - Class object as function argument: Object only - Class not in argument

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")

Python - Accepting extra keyword arguments in class initialization

class Foo:
def __init__(self, id: int, username: str):
self.id = id
self.username = username
dict = {'id':1,'username':'bar', 'extra':0}
x = Foo(**dict) # Foo.__init__() got an unexpected keyword argument 'extra'
I'm working with some web services that sometimes have extra data in the response that I don't care about. The simplified example above illustrates the problem. Is there a way to use a dictionary to initialize an object, without manually entering each desired key as an argument?
Rather than trying to somehow ignore extraneous arguments, why not take a more flexible approach by accepting all parameters regardless of the order in which they are presented to the class constructor.
Then declare properties (getters & setters) to subsequently access the values.
For example:
class Foo:
def __init__(self, **kwargs):
self.kwargs = kwargs
#property
def username(self):
return self.kwargs.get('username')
#username.setter
def username(self, value):
self.kwargs['username'] = value
#property
def ident(self):
return self.kwargs.get('ident')
#ident.setter
def ident(self, value):
self.kwargs['ident'] = value
def __repr__(self):
return ', '.join(f'{k}={v}' for k, v in self.kwargs.items())
f = Foo(ident=123)
print(f.ident)
print(f.username)
f.username = 'Lancelot'
print(f.username)
print(f)
Output:
123
None
Lancelot
ident=123, username=Lancelot
The only disadvantage to this that I can think of (there may be others) is that you would not be able to distinguish between values that were not passed to the constructor and those that had a value of None. You'd need to make your getters more elaborate to handle that

Why Am I getting "missing 1 positional argument" error for this class?

I have a simple class. I want to set the periodicity property using a private attribute which is tested before being used to set the public attribute. I am passing self around the class module, when I run the test code the function seems to expect 2 arguments. I thought it should ignore self and ask for the one freq parameter. I am trying to be "pythonic" and use #property with .setter. Do I need to change the property call? If I remove self from set_periodicity it says it does not recognize self.
class ModelSetUp:
def __init__(self):
self.periodicity= None
#property
def set_periodicity(self,freq):
self.periodicity = self._periodicity
#set_periodicity.setter
def set_periodicity(self,freq):
if freq in ("Q","S","A"):
self._periodicity = freq
else:
raise ValueError("Frequency Must Be Q, S or A")
if __name__=="__main__":
mod = ModelSetUp()
mod.set_periodicity("Q")
Properties don't take any arguments, nor are they callable. Try this:
class ModelSetUp:
def __init__(self):
self._periodicity = None
#property
def periodicity(self):
return self._periodicity
#periodicity.setter
def periodicity(self, freq):
if freq in ("Q","S","A"):
self._periodicity = freq
else:
raise ValueError("Frequency Must Be Q, S or A")
if __name__=="__main__":
mod = ModelSetUp()
mod.periodicity = "Q"

Error Using Class Method Defined Outside of Class

I have a class that I want to take an arbitrary method at initialization to use for string parsing depending on the context.
Using a method defined outside of a class as discussed here: Python define method outside of class definition?
def my_string_method(self):
return self.var.strip()
class My_Class():
def __init__(self, string_method):
self.var = ' foo '
self.string_method = string_method
def use_string_method(self):
return self.string_method()
instance = My_Class(string_method=my_string_method)
print instance.use_string_method()
I get the error "TypeError: use_string_method() takes exactly 1 argument (0 given)".
Shouldn't the self argument be passed implicitly to use_string_method?
Is there a way to define the function such that this occurs, or do I need to explicitly pass the self argument to methods defined outside of the class as such:
class My_Class():
def __init__(self, string_method):
self.var = ' foo '
self.string_method = string_method
def use_string_method(self):
return self.string_method(self)
You will have to wrap the passed in function in "MethodType".
From within your init:
self.string_method = types.MethodType(string_method, self)
This binds the method to the class and allows it to receive the implicit self parameter. Make sure you import types at the top of your script.

How to convert keyword argument to named argument in python 2.7?

1st file:
class Profile(object):
def __init__(self, name, 1st_arg=gst(), 2nd_arg=1, 3rd_arg=AB.parallel):
self.name = name
self.gain = 1st_arg(i, o, p)
self.channel = 2nd_arg
self.mode = 3rd_arg
2nd file:
class A:
some_function():
1st_arg = gst(i, o, p) # class gst constructor
result = Profile(Name, 1st_arg, 2nd_arg=1, 3rd_arg=Phase) # profile class constructor
I have above code, but i want to change "1st_arg" to named argument from keyword argument.
Here 2nd_arg and 3rd_arg arguments clearly specify to whom their values are being assigned, but not the same in 1st_arg.
I want this change so that if some 3rd party saw my code then he would understand it easily.
If you want to convert a positional argument to a keyword argument (and it's the last keyword argument), just specify its name. For example, if you have a call of the following form:
f(val1, val2, arg3=val3, arg4=val4)
and you want to provide val2 as a keyword argument, just call it like
f(val1, arg2=val2, arg3=val3, arg4=val4)
If the argument you want to convert isn't the last positional argument, you'll have to convert all following positional arguments to keyword arguments, too.
Easy, just change the argument from a keyword argument to a positional argument:
class Profile(object):
def __init__(self, name, gst, 2nd_arg=1, 3rd_arg=AB.parallel):
self.name = name
self.gain = gst(i, o, p)
self.channel = 2nd_arg
self.mode = 3rd_arg
You had a bigger problem, though. Calling a function in a method signature in Python only calls that function once, at compile-time. So, if you were noticing some unusual behavior related to gst() being in the method signature, that's why. If you pass a function reference as an argument, it can be called later. Don't call the gst() in the method signature itself, just pass it in as gst.
Edit: I think this is what you're after
class Profile(object):
def __init__(self, name, 1st_arg=gst(sane, default, args), 2nd_arg=1, 3rd_arg=AB.parallel):
self.name = name
self.gain = 1st_arg
self.channel = 2nd_arg
self.mode = 3rd_arg
value = gst(i, o, p)
result = Profile(Name, 1st_arg=value, 2nd_arg=1, 3rd_arg=Phase)

Categories

Resources