Can I add methods into def __init__? - python

Using python 2.7.6, I have been trying to write a class that can extract pieces of xml data from a couple of xml files within a given zip file. I want to be able to use any of the methods in any order once I am working with the class, so wanted the unzip stage to be behind the scenes, in the class.
It is the first time I have really tried to make real use of a class as I am quite new to python, so I am learning as I go.
I defined methods to unzip the data to memory and was using those methods in other methods - then realised it would be horribly inefficient when using multiple methods. Since the unzipping step is necessary for any method in the class, is there a way to build it into the init definition so it is only done once when the class is first created?
Example of what I currently have:
class XMLzip(object):
def __init__(self, xzipfile):
self.xzipfile = xzipfile
def extract_xml1(self):
#extract the xmlfile to a variable
def extract_xml2(self):
#extract xmlfile2 to a variable
def do_stuff(self):
self.extract_xml1()
....
def do_domethingelse(self):
self.extract_xml1()
Is there a way to do something like I have shown below? And if so, what is it called - my searches haven't been very effective.
class XMLzip(object):
def __init__(self, xzipfile):
self.xzipfile = xzipfile
def extract_xml1()
# extract it here
def extract_xml2()
# extract it here
# Now carry on with normal methods
def do_stuff(self):
...

in the __init__ you can do whatever you want in order to initialize your class, in this case look like what you need is something like this
class XMLzip(object):
def __init__(self, xzipfile):
self.xzipfile = xzipfile
self.xml1 = #extract xml1 here
self.xml2 = #extract xml2 here
def do_stuff(self):
...
if you want to do the extract part only once, then do it and save result in a additional attribute in the instance of your class.
I suspect that the extract procedure is very similar, so you can make it a function be inside your class or outside, that is up to your preference, and give additional arguments to handle the specificity, for example something like this
the outside version
def extract_xml_from_zip(zip_file,this_xml):
# extract the request xml file from the given zip_file
return result
class XMLzip(object):
def __init__(self, xzipfile):
self.xzipfile = xzipfile
self.xml1 = extract_xml_from_zip(xzipfile,"xml1")
self.xml2 = extract_xml_from_zip(xzipfile,"xml2")
def do_stuff(self):
...
the inside version
class XMLzip(object):
def __init__(self, xzipfile):
self.xzipfile = xzipfile
self.xml1 = self.extract_xml_from_zip("xml1")
self.xml2 = self.extract_xml_from_zip("xml2")
def extract_xml_from_zip(self,this_xml):
# extract the request xml file from the zip_file in self.xzipfile
return result
def do_stuff(self):
...

You can call any method you have defined in your class in your initializer.
Demo:
>>> class Foo(object):
... def __init__(self):
... self.some_method()
... def some_method(self):
... print('hi')
...
>>> f = Foo()
hi
I take from your question that you need to extract the files only once. Leave your class as is and use your extract methods in __init__ and set the required attributes/variables for the extracted content.
For example
def __init__(self, xzipfile):
self.xzipfile = xzipfile
self.extract1 = self.extract_xml1()
self.extract2 = self.extract_xml2()
This of course requires your extract methods to have a return value, don't forget that.

Related

Python file organization for chainable functions

I'm writing a Python3.x framework that has generators and filters. I have a compact syntax for chaining the output of generators and filters into filters, but file organization feels inelegant. Here's what I mean.
Assume Renderer is the super class for both generators and filters:
# file: renderer.py -- defines the common superclass used by generators and filters
class Renderer(object):
def render():
# Every subclass provides a `render` function that emits some data...
pass
# file: gen1.py -- defines a generator
class Gen1(Renderer):
def __init__(self):
super(Gen1, self).__init__()
def render(self):
... emit some data
# file: filt1.py -- defines a filter that takes any Renderer object as an input
class Filt1(Renderer):
def __init__(self, input, param):
super(Filt1, self).__init__()
self._input = input
self._param = param
def render():
... call self._input.render() to fetch and act on data before emitting it
# file: filt2.py -- defines a filter that takes any Renderer object as an input
class Filt2(Renderer):
def __init__(self, input):
super(Filt2, self).__init__()
self._input = input
def render():
... call self._input.render() to fetch and act on data before emitting it
# file: render_module.py -- a module file to bring in all the components
from renderer.py import Renderer
from gen1.py import Gen1
from filt1.py import Filt1
from filt2.py import Filt2
What I'd like
What I'd like is for a user of the platform to be able to write code like this, which chains the output of gen1 into filt1, and the output of filt1 into filt2:
import render_module as rm
chain = rm.Gen1().filt1(123).filt2()
chain.render()
What I've done
What I've done is add the following to renderer.py. This works, but see "The Problem to Solve" below.
class Renderer(object):
def render():
# emit some data...
pass
def filt1(self, param):
return rm.Filt1(self, parm)
def filt2(self):
return rm.Filt1(self)
import render_module as rm # at end of file to avoid a circular dependency
The Problem to Solve
It feels wrong to pollute the common superclass with specific mentions of each subclass. The clear indication of code smell is the import statement at the end of renerer.py.
But I haven't figured out a better way to refactor and organize the files. What's the pythonic approach out of this conundrum?

How to initialize an object coming from another class?

I have a function in a class (TableManager) that get the item and a specific field ('body') in DynamoDB.
class TableManager:
def get_body_dynamo(self, item):
get_body = json.loads(item.get('txt_vlr_parm_requ').get('body')) ##dict
return get_body
I need to initialize this 'body' field in another class (S3Connection), but I'm having trouble calling this function inside init.
class S3Connection:
def __init__(self, file, logs):
self.file = file
self.logs = logs
self.versions = None
I need something like this, to use this body I got from Dynamodb and create functions.
class S3Connection:
def __init__(self, file, logs, body_dynamo: TableManager.get_body_dynamo()):
self.body_dynamo = body_dynamo
self.file = file
self.logs = logs
self.versions = None
This way, of course, is giving error (not recognizing what body_dynamo is).
I'm new in programming and Python, so I appreciate any help.

How can you pass a user configurable dict into a class instance

I have a class that makes objects allowing me to access properties of an experimental camera system. I have some configuration properties saved in a dict for where certain cameras should be initially located. As these initial settings may vary I cannot hard code them into the class but need them separate in a text file that I access using the json library.
Is there a way to pass the dict into a class so its key value pairs can be used?
Simplified code
import any_dict_01
import json
data = any_dict_01
class dummy(data):
def __init__(self):
self.data = data
def getDict(self):
print(self.data)
a = dummy()
a.getDict()
Working Code
based on hints and advice from karl in the comments under the question I figured out how to do it (I hope karl puts his comments as an answer so I can accept it).
import json
data = 'my_rig.txt'
class dummy:
def __init__(self, data):
self.data = data
def getDict(self):
with open(data) as json_file:
data = json.load(json_file)
print(data)
a =dummy()
theDict = a.getDict(data)
By request:
data = any_dict_01 does not make data be any particular dict defined by the any_dict_01 module. It makes data be another name for that same module.
Anyway, this question isn't really about classes. The way you get information into the __init__ method is the same way that you get information into any ordinary function: by giving it a parameter, and passing the information in as an argument.
Your code would work by fixing the last part like this:
def __init__(self, data):
self.data = data
def getDict(self):
return self.data
a = dummy(data)
theDict=a.getDict()
You can make the dict accessible with dot notation, as if it were a class instance, like this.
class dummy:
def __init__(self, my_dict):
self.my_dict = my_dict

Does a class instance that shares access between coroutines need a asyncio Lock?

For a project I am writing a class that holds data to be shared by multiple coroutines, a basic example would be:
import copy
class Data:
def __init__(self):
self.ls = []
self.tiles = {}
def add(self, element):
self.ls.append(element)
def rem(self, element):
self.ls.remove(element)
def set_tiles(self, t):
self.tiles = t
def get_tiles(self):
return copy.deepcopy(self.tiles)
And it would be used like this:
async def test_coro(d):
# Do multiple things including using all methods from d
test_data = Data()
# Simultaneously start many instances of `test_coro` passing `test_data` to all of them
I'm struggling to understand when you would need to use a lock in a situation like this, my question about this code is would I need to use an asyncio Lock at all, or would it be safe as all variable access / assigning happens without any awaiting inside the class?

How do I best store API data into a Python class instance variable?

I would like some advice on how to best design a class and it's instance variables. I initialize the class with self.name. However, the main purpose of this class it to retrieve data from an API passing self.name as a parameter, and then parsing the data accordingly. I have a class method called fetch_data(self.name) that makes the API request and returns ALL data. I want to store this data into a class instance variable, and then call other methods on that variable. For example, get_emotions(json), get_personality_traits(json), and get_handle(json), all take the same dictionary as a parameter, assign it to their own local variables, and then manipulate it accordingly.
I know I can make fetch_data(self.name) return data, and then call fetch_data(self.name) within the other methods, assign the return value to a local variable, and manipulate that. The problem is then I will need to call the API 5 times rather than 1, which I can't do for time and money reasons.
So, how do I make the result of fetch_data(self.name) global so that all methods within the class have access to the main data object? I know this is traditionally done in an instance variable, but in this scenario I can't initiliaze the data since I don't have it until after I call fetch_data().
Thank you in advance!
It seems like you just need to do something like this:
class Foo(object):
def __init__(self, name):
self.name = name
self.data = None
def fetch_data(self):
if self.data is None:
# Only call the API once
self.data = self.really_fetch_data()
return self.data
def get_emotions(self):
emotions = self.fetch_data().get("emotions")
...
Why don't you just try to solve this as you described?
For example, you can take this as a starting point:
import json
class APIBundle(object):
def __init__(self, name):
self.name = name
self.data = None
self.update()
def update():
response = json.loads(API_request(self.name))
# Do some parsing on response
self.data = response
def get_emotions():
# Work through current data state
# and filter as desired
result = []
for message in self.data['messages']:
if message.find(':)') != -1:
result.append((message, 'positive'))
if message.find(':(') != -1:
result.append((message, 'negative'))
return result
if __name__ == '__main__':
ab = APIBundle('my-secret-name')
print(self.get_emotions())
Try to do it with self.data=None , or make an instance variable and call whenever you need. writing algorithm will make this thing more complex try to solve issue with inbuilt functions or with algorithm program vulnerability will affect alot.

Categories

Resources