Python: how to overwrite what print(dict) outputs? - python

I have a dictionary, and a print statement as follows:
d = {'ar':4, 'ma':4, 'family':pf.Normal()}
print(d)
Which gives me
{'ar': 4, 'ma': 4, 'family': <pyflux.families.normal.Normal object at 0x11b6bc198>}
Is there any way to clean up the value of the 'family' key? It's important that the calls remains simply 'print(d)' because it used to print other dictionaries without this issue. Is this possible? Thanks for your time.
EDIT:
Thanks for the answer guys, I would mark one as right but I haven't tried them and can't confirm. I ended up creating another dictionary with the cleaned up string as a key, and the object as the value. It was a bit more work but I did it before reading/getting the responses so I just stuck to it. Thanks nonetheless!

You are mistaken. You don't want to change what print(dict) outputs. That would require changing the way builtin dictionaries are printed. You want to add a custom __repr__() to your pf.Normal() object.
I believe pf.Normal() comes from the pyflux package, so I suggest seeing what data the class is suppose to hold, and pretty printing it by inheriting from the class:
class CustomNormalObject(pf.Normal):
def __repr__(self):
# Add pretty printed data here
pass
Or if you need to pass your own arguments into the custom class, you can use super():
class CustomNormalObject(pf.Normal):
def __init__(self, myparm, *args, **kwargs):
# If using Python 3, you can call super without
# passing in any arguments. This is simply for Python 2
# compatibility.
super(CustomNormalObject, self).__init__(*args, **kwargs)
self.myparm = myparm
def __repr__(self):
# Add pretty printed data here
pass

as I think pyflux is an external library, I think you should not edit it directly. An easy way to do what you want is to overwrite the __str__ or __repr__ methods of the Normal class.
pyflux.families.normal.Normal.__str__ = lambda self: "Clean up value here."
Here I used a lambda function for illustration, but of course you can use a defined function.

Related

Python: can I unpack arguments without calling a function?

I have dict that I want to convert to several different objects. For instance:
Currently Have
kwargs = {'this': 7, 'that': 'butterfly'}
And I want to convert it, maybe using something similar to function argument unpacking, but without actually calling a function, so that I end up with something like:
Desired
**kwargs
print(this) # Will print out `7`
print(that) # Will print out `'butterfly'`
I know that I cannot use the double-star [**] bare like I have shown. But is there something similar I can do?
Edit: More Specifics
Since folks were asking for details and warning that what I am trying to do is dangerous, I will give more context for my need.
I have a property in a class that I want to set using keyword arguments. Something like what is shown here, but unpacking kwargs instead of args.
As a functioning toy example, it looks like this:
class A(object):
def __init__(self):
self._idx = None
#property
def idx(self):
return self._idx
#idx.setter
def idx(self, kwargs):
print(kwargs)
self._idx = {}
for kw, val in kwargs.items():
self._idx[kw] = val
This works. But now I am unit testing the function, and in the unit test, I would like to be able to provide the specific key-value pairs as normal objects, so that I can effectively use hypothesis and pytest's #mark.parametrize effectively.
In order to do this, it looks like I will need the "bare unpacking" like I described above.
Since these are all actually local variables within a method, I feel like #g.d.d.c's concerns are probably not significant. It sounds like his worries were if I created new global variables without knowing what they were.
Note: this approach is dangerous. You should not (in most circumstances) muddle with locals() or globals(). However, what you want can be done, kind of:
>>> kwargs = {'this': 7, 'that': 'butterfly'}
>>>
>>> locals().update(kwargs)
>>> this
7
>>> that
'butterfly'
It still calls a function (the update on locals()) but it does give you names in your local namespace.
You could do:
this, that = {"this": 7, "that": "butterfly"}.values()
But it is really specific. The question would be why do you have the values in a dict in the first place.
You seem to have them in kwargs, why cannot you expend them there?
If you don't know the keys in the dict how can you then use them in the code?
If you know the keys in the dict, why not simply expand it like so:
this, that = kwargs["this"], kwargs["that"]
And my final question? Why not use kwargs["this"] where you need the variable, especially if you don't need it a lot.
Can you provide us with the real use case so that we can tell you how we would do that?

Overwriting bound methods in python when function requires class attribute

Say I have a class:
class Data():
def __init__(self):
self.scores = []
self.encoding= {1: 'first', 2: 'second', 3:'third'}
def build():
self.scores = [1, 2, 3]
def translate(self):
return [self.encoding[score] for val in self.scores]
Now I want to be able to translate the columns for a given data object...
# I want to be able to do
d= Data()
d.scores.translate()
# AttributeError: 'list' object has no attribute 'translate'
# Instead of
d= Data()
d.translate()
Now I am fully aware that I am trying to access a method that does NOT exist for that list (translate()). I want to be able to make method calls as is mentioned above (d.scores.translate()) because I may have some specific subslice of d.scores I want to translate.
For Example, if d.scores was a nested numpy array (I only want to translate 1st 5 columns but keep all rows)
#this is what I would like to be able to do
d.scores[:, 1:5].translate()
# And I don't want to build a kwarg in the translate method to handle it like
d.scores.translate(indices=[1])
I know this is more of an implementation question, and I'm wondering what the best practice should be.
Am I trying to force a square peg into a round hole at this point? Should I just give up and define a module function or consider the kwargs? Is that more 'pythonic'?
UPDATE
I should have said this sooner but I did try using the kwarg and staticmethod route. I just want to know if there are other ways to accomplish this? Maybe through subclassing? or Python's equivalent of interfacing in java/C# (if it exists?)
Yes, you are trying to "force a square peg into a round hole".
Your translate method works on the whole scores list, full stop. This can not be changed with some trickery, which is simply not supported in Python.
When you want to do subslices, I would recommend doing it explicitly.
Examples:
# Using args/kwargs:
scores = john.translate(10, 15) # translate subslice 10:15
# Using a new static method:
scores = Person.translate_scores(john.scores[10:15])
Looks not that elegant, but works.
(BTW: Since you changed your question, my classes might be a little of, but I will not change my answer with every edit you make)
Your trickery simply does not work, because "scores" is not some part of your main class, but simply an attribute of it, which has its own type. So, when you do "d.scores.translate()" translate is not called on d, but on a list or whatever type scores is. You can not change that, because it is core Python.
You could do it by using a second class and use _scores for the list and a sub-object scores which manipulates _scores:
class DataHelper(object):
def __init__(self, data_obj):
self.data_obj = data_obj
def translate(self, *args):
... # work on self.data_obj._scores
class Data(object):
def __init__(self):
self.scores = DataHelper(self)
self._scores = []
With such a class structure, you might be able to to this:
scores = d.scores.translate(1, 5)
And with more trickery, you might be able to even do:
scores = d.scores[1:5].translate()
But for that, you will need a third class (objects of that will be created temporary on indexing scores objects, so that d.scores[1:5] will not create a list slice but a new object with translate method).

returning functions from a method in python

I have tried looking into the documentation and google search , but I am unable to find out the significance of the [clazz] at the end of method. Could someone help me understand the meaning of the [clazz] at the end of the method? Thanks.
def get_context_setter(context, clazz):
return {
int: context.setFieldToInt,
datetime: context.setFieldToDatetime
}[clazz]
setFieldToInt and setFieldToDatetime are methods inside context class.
This function returns one of two things. It returns either context.setFieldToInt or context.setFieldToDatetime. It does so by using a dictionary as what would be a switch statement in other programming languages.
It checks whether clazz is a reference to the class int or a reference to the class datetime, and then returns the appropriate method.
It's identical to this code:
def get_context_setter(context, clazz):
lookup_table = {int: context.setFieldToInt,
datetime: context.setFieldToDatetime
}
context_function = lookup_table[clazz] # figure out which to return
return context_function
Using a dict instead of a switch statement is pretty popular, see Replacements for switch statement in Python? .
More briefly.
The code presented is expecting the class of some object as a parameter poorly named as clazz.
It's then using that class as a dictionary key.
They're essentially trying to accept two different types and call a method on the object type.
class is a keyword in Python.
The author of the code you show chose to use a strange spelling instead of a longer snake_case parameter name like obj_class.
The parameters really should have been named obj, obj_class
Or
instance, instance_class
Even better, the class really need not be a separate parameter.

Convert String to Object name

I needed help on this one. How do I convert a string into a variable/object/instance name, since I don't know how to categorize this. Assuming my code is:
a = {}
b = {}
class Test:
def getKeys(self, var):
return var.keys() #where var refers to the dictionary and its a string initially
It's been forever since I've done anything with Python but I do remember having this problem once. I suggest you look into the eval() function.
If I understand correctly, your variable var is a string that might be "a" or "b". You want to use that letter to pick the correct dictionary global variable to look in.
I suggest putting your dictionaries into another dictionary, with keys you can use to look it up by name:
my_dicts = {"a":a, "b":b}
class Test:
def getkeys(self, dict_name):
return my_dicts[dict_name].keys()
However, this may be simply an issue of design. Instead of sending a variable name to the getkeys method, why not simply send the dictionary itself and use your current code?
Instead of Test().getkeys("a"), call Test().getkeys(a) (no quotation marks).
You're looking for the setattr builtin method. You'll also need an object to perform this on.
obj = lambda: None # Create an empty object without needing to make a class (functions are objects)
setattr(obj, "hello", "world")
obj.hello # returns "world"

Creating Python class with regular expressions

I apologize for the newbie question, but this is my first time working with classes. The class I'm trying to create is intended to perform a regex find and replace on all keys and values within a dictionary. The specific find and replace is defined upon instantiation.
There are two issues that I have. The first issue is that each instance of the class needs to accept a new dictionary. I'm not clear on how to create a class that accepts a general dictionary which I can specify upon creating an instance.
The second issue is that the class I have simply isn't working. I'm receiving the error message TypeError: expected string or buffer in the class line v = re.sub(self.find,self.replace,v).
There are three instances I want to create, one for each input dictionary: input_iter1, input_iter2, and input_iter3.
The following is the class:
class findreplace:
values = []
keys = []
def __init__(self, find, replace):
self.find = find
self.replace = replace
def value(self):
for k,v in input_iter1.items():
v = re.sub(self.find,self.replace,v)
findreplace.values.append(v)
def key(self):
for k,v in input_iter1.items():
k = re.sub(self.find,self.replace,k)
findreplace.keys.append(k)
The following are the instances:
values1 = findreplace('[)?:(]','')
values1.value()
values2 = findreplace(r'(,\s)(,\s)(\d{5})({e<=1})',r'\2\3')
values2.value()
keys1 = findreplace(r'(?<=^)(.+)(?=$)',r'(?:\1)')
keys1.key()
keys2 = findreplace(r'(?=$)',r'{e}')
keys2.key()
print values
print keys
If anyone has any insight on how I can workaround these two issues, I'd be grateful to hear them. Thanks!
First, Python 2 classes should start off this way:
class Foo(object):
Otherwise, you get an "old-style class", which is some ancient crusty thing no one uses.
Also, class names in Python are typically written in CamelCase.
Second, do not use mutable values (like lists!) as class attributes, as you're doing here with keys and values. They'll be shared across all instances of your class! It looks like you're even aware of this, since you refer to findreplace.keys directly, but it doesn't make sense to store instance-specific values in a class attribute like that.
But, most importantly: why is this a class at all? What does a findreplace represent? It looks like this would be much clearer if it were just a single function.
To answer your actual questions:
You pass in a dictionary just like you're passing in find and replace. Add another argument to __init__, and pass another argument when you construct your class.
Presumably, you're getting the TypeError because one of the values in your dictionary isn't a string, and you can only perform regexes on strings.
Where is your definition of the input_iter dicts? How do they look like? Your error indicates that the values of your dicts are not strings.

Categories