Python How to call a class method without importing - python

I found this piece of code in this repo. https://github.com/adw0rd/instagrapi/blob/master/instagrapi/mixins/fbsearch.py
And I wonder how self.private_request() could be called because there is no import and private_request() isn't defined in this class.
from instagrapi.extractors import extract_location
class FbSearchMixin:
def fbsearch_places(self, query: str, lat: float = 40.74, lng: float = -73.94):
params = {
'search_surface': 'places_search_page',
'timezone_offset': self.timezone_offset,
'lat': lat,
'lng': lng,
'count': 30,
'query': query,
}
result = self.private_request("fbsearch/places/", params=params)
locations = []
for item in result['items']:
locations.append(extract_location(item['location']))
return locations
It would be glad if someone could explain why and how this is possible.

This code doesn't call fbsearch_places; only defines it. If it called it without defining private_request, that would cause an exception.
But if someone imports this code and uses this class in combination with another class where private_request is defined, then they will be able to use the fbsearch_places method.
That's what "mix in" means in FbSearchMixin: that the class that is supposed to be used in combination with another class in multiple inheritance.

Related

How to init a value in a class with a simple setting and getting attributes?

The class I have been using looks simple, like this:
class Transaction(dict):
__getattr__ = dict.get
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
and then sending in:
transaction = Transaction({"to": "0x000", "from": "0x001": "timestamp": 1234})
and of course can be used like this transaction.to, however it looks like transaction.from does not work because from is a python reserved keyword
So I am curious using that simple class, is there a way to reassign from in the class to be something like
self.sender = dict.from
I have been trying with __init__ but with no luck
I also have written the class just with an __init__ and then assigning all values using self but with out a getter the class is not iterable
What I have been doing looks like this
# given data - {"to": "0x000", "from": "0x001": "timestamp": 1234}
item["sender"] = item["from"]
transaction = Transaction(item)
and then I have reference to it like transaction.sender.
If I understand correctly, your end goal is to have a class that can be instantiated from a dict and expose the keys as attributes. I'm inferring that the dict can only contain certain keys since you're talking about mapping "from" to sender. In that case, I would do this completely differently: don't subclass dict, instead have an alternate constructor that can handle the dict. I'd keep a "normal" constructor mostly for the sake of the repr.
For example:
class Transaction:
def __init__(self, to, from_, timestamp):
self.to = to
self.from_ = from_
self.timestamp = timestamp
#classmethod
def from_dict(cls, d):
return cls(d['to'], d['from'], d['timestamp'])
def __repr__(self):
"""Show construction."""
r = '{}({!r}, {!r}, {!r})'.format(
type(self).__name__,
self.to,
self.from_,
self.timestamp)
return r
transaction = Transaction.from_dict({"to": "0x000", "from": "0x001", "timestamp": 1234})
print(transaction) # -> Transaction('0x000', '0x001', 1234)
print(transaction.from_) # -> 0x001
Here I'm using the trailing underscore convention covered in PEP 8:
single_trailing_underscore_: used by convention to avoid conflicts with Python keyword, e.g.
tkinter.Toplevel(master, class_='ClassName')
By the way, if it's useful, the keyword module contains the names of all Python keywords.

Python: mapping between class and json

I am getting Data via a REST-Interface and I want to store those data in a class-object.
my class could looks like this:
class Foo:
firstname = ''
lastname = ''
street = ''
number = ''
and the json may look like this:
[
{
"fname": "Carl",
"lname": "any name",
"address": ['carls street', 12]
}
]
What's the easiest way to map between the json and my class?
My problem is: I want to have a class with a different structure than the json.
I want the names of the attributes to be more meaningful.
Of course I know that I could simply write a to_json method and a from_json method which does what I want.
The thing is: I have a lot of those classes and I am looking for more declarative way to write the code.
e.g. in Java I probably would use mapstruct.
Thanks for your help!
Use a dict for the json input. Use **kwargs in an __init__ method in your class and map the variables accordingly.
I had a similar problem, and I solved it by using #classmethod
import json
class Robot():
def __init__(self, x, y):
self.type = "new-robot"
self.x = x
self.y = y
#classmethod
def create_robot(cls, sdict):
if sdict["type"] == "new-robot":
position = sdict["position"]
return cls(position['x'], position['y'])
else:
raise Exception ("Unable to create a new robot!!!")
if __name__=='__main__':
input_string = '{"type": "new-robot", "position": {"x": 3, "y": 3}}'
cmd = json.loads(input_string)
bot = Robot.create_robot(cmd)
print(bot.type)
Perhaps you could you two classes, one directly aligned with the Json (your source class) and the other having the actual structure you need. Then you could map them using the ObjectMapper class[https://pypi.org/project/object-mapper/]. This is very close to the MapStruct Library for Java.
ObjectMapper is a class for automatic object mapping. It helps you to create objects between project layers (data layer, service layer, view) in a simple, transparent way.

How to create objects from jsons in python with a complex constructor?

I am trying to create a blockchain and need a function to put my Blocks into json format and be able to create objects again. This seems quite difficult, since my constructor does not take all the attributes as parameters. My constructor looks like this:
class Block:
id = 0
def __init__(self, transaction, prevhash):
self.transactions = []
self.transactions.append(transaction)
self.prevhash = prevhash
self.timestamp = time.time()
self.id = Block.id
Block.id = Block.id + 1
I encode them the following (which seems to work perfectly fine):
def to_json(self):
return json.dumps(self, indent=4, cls=BlockEncoder)
class BlockEncoder(JSONEncoder):
def default(self, o):
return o.__dict__
It creates that output for me (just an example):
{
"transactions": [
{
"ipfshash": 1,
"title": null,
"length": null,
"id": 0
},
{
"ipfshash": 3,
"title": null,
"length": null,
"id": 2
}
],
"prevhash": 10,
"timestamp": 1591350715.1794589,
"id": 0
}
What im trying now to get it into an object again is (i need a generator like object to call the function, but it works. Still trying to figure out how i can make that one static :D)
def from_json(self, jsondict):
return json.loads(jsondict, object_hook=custom_block_decoder)
def custom_block_decoder(jsondict):
return namedtuple('Block', jsondict.keys())(*jsondict.values())
So, if I do that with some element and print it, it wont use my defined __str__ function, also I cant call any other function of my Block class. It seems that namedtuple('Block', jsondict.keys())(*jsondict.values()) just names my object type "Block" but does not really apply anything to it to make it an object. I can call element.attribute, but cant call for element.to_json() again, since the error message is AttributeError: 'Block' object has no attribute 'to_json'. I thought about decoding it per hand, but since I cant use multiple constructors that does not seem a good idea. Would be great if somebody could help me
Why are you using namedtuple?
It seems that namedtuple('Block', jsondict.keys())(*jsondict.values())
just names my object type "Block" but does not really apply anything to it to make it an object.
Everything is an object. namedtuple is a factory function that creates a subclass of tuple that supports named attribute access, but it is still a tuple. I'm not sure why would you expect it to be an instance of the custom Block class that you defined. It doesn't make much sense to use it here.
In any case, you have to write the deserialization routine yourself. In general, this would look something like
class Foo:
def __init__(self, bar):
self.bar = bar
self.baz = 42
def frobnicate(self):
baz = self.baz
self.baz = self.baz ** 2 // 4
#classmethod
def from_dict(cls, dict_foo):
foo = cls.__new__(cls) # just object.__new__
# here is where you have to implement the logic yourself to rebuild your object.
# hopefully it doesn't get too complex
foo.__dict__.update(dict_foo)
return foo
Note, using a classmethod is customary, then you can use
Foo.from_dict({'bar': 8, 'baz': 42})
And it plays a bit better with inheritance. These sorts of classmethods are usually referred to as alternative constructors.

How to Add a Method to a Method In a Class?

Let's say I have the following class:
import webbrowser
class Management(object):
def add_accounts(self, data):
operations = []
for account_name in data:
operations.append(
{'operator': 'ADD',
'operand': {'name': account_name}
})
self.added = operations
manager = Management()
manager.add_accounts(['name 1', 'name 2'])
What I want to do is add this function:
def source():
url = r'http://www.stackoverflow.com/some-help-doc'
webbrowser.open(url, new=1)
to the add_accounts method so I can type the following:
manager.add_accounts.source()
and have it open my default browser to the help article online:
I've been searching for how to add a method to an already existing method in a class. Is there a name for what I'm trying to do?
As #BrenBam pointed out in comments, methods do have attributes and those can be anything, including functions. However, this'll make for some weird un-Pythonic code. If you want this method to show some kind of documentation (as example suggests), it'll be better to just copypaste information to a docstring. Docstring is where everyone expects info to be.
This seems like the best option for now:
import webbrowser
class Management(object):
def __init__(self):
Management.add_accounts.source = lambda url='https://github.com/': webbrowser.open(url, new=1)
def add_accounts(self, data):
operations = []
for account_name in data:
operations.append(
{'operator': 'ADD',
'operand': {'name': account_name}
})
self.added = operations
manager = Management()

XML to Python Class to C Struct

I need some advice. Two questions, does something already exist for this, what modules should I use to develop this.
I have some structures that come from an XML file. I want to represent them in Python Classes (maybe using a factory to create a class per structure). But I want these classes to have a function that will emit the structure as a C Struct.
From my research ctypes seems like the recommended thing to use to represent the structures in Python classes, but I don't see any methods for anything that will emit C Stucts for the creation of a header file.
From OP's comment I think the minimal solution a set of helper functions instead of classes. the xmltodict library makes it easy to turn the XML data into nested dictionaries, more or less like JSON. A set of helpers that parse the contents and generate appropriate C-struct strings is all that's really needed. If you can work with dictionaries :
{
"name": "my_struct",
"members": {
[
"name": "intmember",
"ctype": "int"
},
{
"name": "floatmember",
"ctype": "float"
}
]
}
You can do something like:
from string import Template
struct_template_string = '''
typedef $structname struct {
$defs
} $structname;
'''
struct_template = Template(struct_template_string)
member_template = Template(" $ctype $name;")
def spec_to_struct(spec_dict):
structname = spec_dict['name']
member_data = spec_dict['members']
members = [member_template.substitute(d) for d in member_data]
return struct_template.substitute(structname = structname, defs = "\n".join(members))
Which will produce something like:
typedef my_struct struct {
int intmember;
float floatmember;
} my_struct;
I'd try to get it working with basic functions first before trying to build up a class scaffold. It would be pretty easy to hide the details in a class using property descriptors:
class data_property(object):
def __init__(self, path, wrapper = None):
self.path = path
self.wrapper = wrapper
def __get__(self, instance, owner):
result = instance[self.path]
if self.wrapper:
if hasattr(result, '__iter__'):
return [self.wrapper(**i) for i in result]
return self.wrapper(**result)
return result
class MemberWrapper(dict):
name = data_property('name')
type = data_property('ctype')
class StructWrapper(dict):
name = data_property('name')
members = data_property('members', MemberWrapper )
test = StructWrapper(**example)
print test.name
print test.members
for member in test.members:
print member.type, member.name
# my_struct
# [{'name': 'intmember', 'ctype': 'int'}, {'name': 'floatmember', 'ctype': 'float'}]
# int intmember
# float floatmember

Categories

Resources