Calling a static method inside a class in python - python

I run into a situation, where I call a static method of a class from another static method. To be sure, that I don't ask an X-Y-question, I'm trying to give some background.
I have a class, that holds a data container and several methods to convert data inside the container. As I also want the converters to be callable from the outside without a class instance, I choose static methods:
class SomeClass(object):
def __init__(self,some_data):
self.data = some_data
#staticmethod
def convert_1(data_item):
return 1+data_item
#staticmethod
def convert_2(data_item):
return 2*data_item
Now I can do SomeClass.convert_1(data_item) without the need to create an instance of SomeClass.
Let's say, I want to have a method inside SomeClass, that does the two converts successively, and also want to have that method as a static method.
Can I do
#staticmethod
def combined_convert(data_item):
data_item = SomeClass.convert_1(data_item)
data_item = SomeClass.convert_2(data_item)
return data_item
inside SomeClass? This feels wrong, as I call the class inside its own definition, but I cannot come up with another 'more pythonic' way.

You can create a class method.
#classmethod
def combined_convert(cls,data_item):
data_item = cls.convert_1(data_item)
data_item = cls.convert_2(data_item)
return data_item

Related

Instantiating and Using a Method of a Class Within a Function

I'm trying to instantiate a class within a function, then call a method within the class inside the same function, like this:
# Define the class
class myclass:
def __init__(self,string_to_print):
self.string_to_print = string_to_print
def myclass_func(self):
print(self.string_to_print)
# Define the function that utilizes the class
def func(class,func,str)
instance = class(str)
class = class.func()
# Run the function that utilizes the class
func(myclass,myclass_func,str)
But I am getting an error like "'myclass' object is not callable". Why is this? Additionally, I expect my 'class = class.func()' line is wrong; if it is, what is the correct way to call the method from the recently instantiated class?
Edit: fixed mistake in class declaration
You can't use method names as global variables. If you want to call a method dynamically, pass its name as a string and use the getattr() function.
# Define the class
class myclass:
def __init__(self,string_to_print):
self.string_to_print = string_to_print
def myclass_func(self):
print(self.string_to_print)
# Define the function that utilizes the class
def func(class,func,str)
instance = class(str)
return getattr(instance, func)()
# Run the function that utilizes the class
func(myclass,'myclass_func',str)
Define your class using the class keyword rather than def.
Create an instance of the class.
Define a function that will try to execute the function given by its name.
class myclass:
def __init__(self,string_to_print):
self.string_to_print = string_to_print
def myclass_func(self):
print(self.string_to_print)
myclass_instance = myclass('Hello world')
def execute_function(instance, function):
getattr(instance, function)()
execute_function(myclass_instance, 'myclass_func')
Output:
Hello world

Python class multiple constructors

There is a class that I want to be constructed from a string in 2 different ways. Here is what I mean:
class ParsedString():
def __init__(self, str):
#parse string and init some fields
def __init__2(self, str):
#parse string in another way and init the same fields
In Java I would provide a private constructor with 2 static factory methods each of which define a way of parsing string and then call the private constructor.
What is the common way to solve such problem in Python?
Just like in java:
class ParsedString():
def __init__(self, x):
print('init from', x)
#classmethod
def from_foo(cls, foo):
return cls('foo' + foo)
#classmethod
def from_bar(cls, bar):
return cls('bar' + bar)
one = ParsedString.from_foo('!')
two = ParsedString.from_bar('!')
docs: https://docs.python.org/3/library/functions.html?highlight=classmethod#classmethod
There's no way, however, to make the constructor private. You can take measures, like a hidden parameter, to prevent it from being called directly, but that wouldn't be considered "pythonic".

Refactor the python design patterns

I have a class called resources and I have defined one method called get_connect. I want to use the data of which get_connect returns to the other classes. I need at least three classes and I use the data of get_connect and I have to parse that data. To implement this I have written the code below
class resources:
#staticmethod
def get_connect():
return 1 + 2
class Source1(resources):
def __init__(self):
self.response = resources.get_connect()
def get__details1(self):
print(self.response)
class Source2(resources):
def __init__(self):
self.response = resources.get_connect()
def get_details2(self):
print(self.response)
class Source3(resources):
def __init__(self):
self.response = resources.get_connect()
def get__detail3(self):
print(self.response)
source1 = Source1()
source2 = Source2()
source3 = Source3()
source1.get__details1()
source2.get_details2()
source3.get__detail3()
But the problem with the code is for every class in init method I am calling the get_connect method. I don't want to repeat the code. I need help for avoiding redundancy which I have asked below
Is there any way I can call get_connect in one place and use it for other classes maybe a decorator or anything? if yes how can I?
While creating objects also I am calling each class and calling each method every time. is there a way to use any design pattern here?
If anyone helps me with these oops concepts it will be useful.
First of all, is there any reason why you are using get_connect method as static?
Because what you can do here is declare it in the parent class:
class resources:
def __init__(self):
self.response = self.get_connect()
def get_connect(self):
return 1 + 2
This way you do not need to define the __init__ method on every class, as it will be automatically inherited from the parent.
Regarding the second question, it really depends on the context, but you can use a strategy pattern in order to retrieve the class that you require to call. For this rename the method of get details into the same for each of the classes, as basically they're used for the same purpose, but changed on the context of the class implementation:
class Source1(resources):
def get_details(self):
print(self.response)
class Source2(resources):
def get_details(self):
print(self.response)
class Source3(resources):
def get_details(self):
print(self.response)
classes = {
"source_1": Source1,
"source_2": Source2,
"source_3": Source3
}
source_class = classes["source_1"]
source = source_class()
source.get_details()
Hope this helped!

Static initializer for Python classes

I'm looking for an equivalent to the static { ... } block in Java that can be used in Python classes. Specifically, I want to be able to access static resources like the arguments of the class constructor and store them in a field of the class, like so:
class A:
constructor_args = A.__init__.__code__.co_varnames
def __init__(self, foo=0, bar=1):
...
This example doesn't work, because class A is not yet initialized when I call A.__init__.__code__.co_varnames.
My current workaround is to alter the static field after the class has been created like so:
class A:
constructor_args = ...
def __init__(self, foo=0, bar=1):
...
constructor_args = A.__init__.__code__.co_varnames
But this solution is rather ugly because I change a static field of a class outside of the class context and if the class contains a lot of code, it's easy to miss out on what is going on here.
So basically I need a way to call a function right after the class has been initialized, and I want to define this function inside of the class.
You will have to at least define the __init__ method first, but you can access its properties immediately after:
class Foo:
def __init__(self, bar, baz):
pass
constructor_args = __init__.__code__.co_varnames
Inside the class block code executes inside its own namespace, so __init__ is directly accessible as __init__.
Here is a simple approach that postpones execution of code that needs the finished class by moving it inside a function defined inside the class body. To have the function called and deleted after use we define a simple decorator:
import inspect
def finalizing(cls):
cls.__finalize__(cls)
del cls.__finalize__
return cls
#finalizing
class example:
def __finalize__(me):
me.constructor_args = list(inspect.signature(me.__init__).parameters)
def __init__(self, x):
pass
example.constructor_args
# ['self', 'x']
You could use a class decorator:
def store_constructor_args(cls):
cls.constructor_args = cls.__init__.__code__.co_varnames
return cls
#store_constructor_args
class A:
def __init__(self, foo=0, bar=1):
x = 10
print(A.constructor_args)
# ('self', 'foo', 'bar', 'x')
#store_constructor_args
class A:
is equivalent to
class A:
...
A = store_constructor_args(A)

python static class with static method that uses self?

I'm doing a database insert script in pycassa. I want to set up a public static class that defines some variables that will get used a lot by other functions later on. Heres what I have...
class ks_refs():
pool = ConnectionPool('TweetsKS')
user_name_cf = self.cf_connect('UserName')
user_tweet_cf = self.cf_connect('UserTweet')
def cf_connect(column_family):
cf = pycassa.ColumnFamily(self.pool, column_family)
return cf
I haven't even tried to run this yet because I'm sure it wont work. You can see I want this static variable 'pool' first, and then set up user_name_cf and user_tweet_cf (and some more later) using the cf_connect method which needs 'pool' to work.
I know I could put that method outside the class, or I could have this non-static and make an instance of it, but I want to try this because this is what I really want (before I was just using globals but I think a static class holding all this is the best idea)
I think you want to have a class method instead:
#classmethod
def cf_connect(cls, column_family):
cf = pycassa.ColumnFamily(cls.pool, column_family)
return cf
Now you can refer to the pool defined on your class with ease.
Your user_name_cf and user_tweet_cf 'attributes' will not work, however. You can add these after having created the class definition:
class ks_refs():
pool = ConnectionPool('TweetsKS')
#classmethod
def cf_connect(cls, column_family):
cf = pycassa.ColumnFamily(cls.pool, column_family)
return cf
user_name_cf = ks_refs.cf_connect('UserName')
user_tweet_cf = ks_refs.cf_connect('UserTweet')
where they are then module-level constants, or you can add them to the class as attributes after the fact:
ks_refs.user_name_cf = ks_refs.cf_connect('UserName')
ks_refs.user_tweet_cf = ks_refs.cf_connect('UserTweet')

Categories

Resources