Can I define my own format specification? - python

I would like to define my own str.format() specification, e.g.
def earmuffs(x):
return "*"+str(x)+"*"
to be used, e.g., like this:
def triple2str(triple, fmt="g"):
return "[{first:{fmt}} & {second:+{fmt}} | {third}]".format(
first=triple[0], second=triple[1], third=triple[2], fmt=fmt)
so that:
## this works:
>>> triple2str((1,-2,3))
'[1 & -2 | 3]'
>>> triple2str((10000,200000,"z"),fmt=",d")
'[10,000 & +200,000 | z]'
## this does NOT work (I get `ValueError: Invalid conversion specification`)
>>> triple2str(("a","b","z"),fmt=earmuffs)
'[*a* & *b* | z]'
The best I could come up with so far is
def triple2str(triple, fmt=str):
return "[{first} & {second} | {third}]".format(
first=fmt(triple[0]), second=fmt(triple[1]), third=triple[2])
which works like this:
>>> triple2str((1,-2,3))
'[1 & -2 | 3]'
>>> triple2str((10000,200000,"z"),fmt="{:,d}".format)
'[10,000 & 200,000 | z]' # no `+` before `2`!
>>> triple2str((10000,200000,"z"),fmt=earmuffs)
'[*10000* & *200000* | z]'
Is this really the best I can do?
What I am unhappy about is that that it is unclear how to incorporate the modifiers (e.g., + above).
Is str.format extensible?

str.format itself is not extensible. However, there are two ways:
1.
Use your custom string formatter: https://docs.python.org/2/library/string.html#custom-string-formatting
Override the format_field(obj, format_spec) method to catch the callable format_spec. Then call your formatter directly.
This code snippet can help you (it works with py 3.5 & 2.7 at least):
import string
class MyFormatter(string.Formatter):
def __init__(self, *args, **kwargs):
super(MyFormatter, self).__init__(*args, **kwargs)
self.fns = {}
def format_field(self, value, format_spec):
# print(repr(value), repr(format_spec))
# intercept {fmt} part with functions:
if callable(value):
result = super(MyFormatter, self).format_field(value, format_spec)
self.fns[result] = value
return result
# intercept {var:{fmt}} with remembered {fmt}:
if format_spec in self.fns:
return self.fns[format_spec](value)
else:
return super(MyFormatter, self).format_field(value, format_spec)
def fn(val):
return '*{}*'.format(val)
f = MyFormatter()
print(f.format("{var:{fmt}}", var=1000, fmt='g'))
print(f.format("{var:{fmt}}", var=1000, fmt=fn))
2.
Define per-object format method __format__(self, format_spec), where format_spec is whatever goes after : in e.g. {var:g}. You can format self-presentation of the object as you wish.
However, in your case, the objects are ints/strs, not the custom objects, so this method will also not help much.
As the conclusion:
Yes, your solution in the question is sufficient and probably the simplest one.

In python 3 you can call functions in f-strings, perhaps this can help.
def earmuffs(val):
return "*{}*".format(val)
form = lambda a: f"method {earmuffs(a[0])} and method {earmuffs(a[1])}"
b = ('one', 'two')
form(b)
>>>'method *one* and method *two*'

Related

Left += Operation for Strings

In Python, the += operation is a right-action, meaning that a+=b is equivalent to a=a+b.
Since, for strings, this operation is not commutative, it raises the question if there is a similar operator for a left-action, i.e. some operator (or other hack) say %= such that a%=b does a=b+a?
Addendum
The solutions so far, except the obvious a=b+a, involved overriding the str.__add__ method which, as pointed out by #BrianJoseph, was not quite what I had in mind since it merely shifts the problem to the other extreme.
The following workaround, involving this amazing hack, illustrates the behaviour I was seeking.
Prelims
# -------------------------------------------------------------
# Following class can be found in Tomer Filiba's blog
# Link provided in the question
from functools import partial
class Infix(object):
def __init__(self, func):
self.func = func
def __or__(self, other):
return self.func(other)
def __ror__(self, other):
return Infix(partial(self.func, other))
def __call__(self, v1, v2):
return self.func(v1, v2)
# -------------------------------------------------------------
# Custom Class
class my_str(str):
def __init__(self, string):
self.string = string
def __str__(self):
return self.string.__str__()
def __repr__(self):
return self.string.__repr__()
#Infix
def left_assign(self, string):
self.string = string + self.string
Example
# Testing
a = my_str('World')
b = 'Hello'
print(a)
# World
a |my_str.left_assign| b
print(a)
# HelloWorld
Of course the line a |my_str.left_assign| b is not exactly easier to write then a = b + a, but this was just an example for illustrations.
Finally, for those to whom my non-edited question might have been unclear: I am (was) wondering if a=b+a can bone writing a just once (analogously to a+=b for a=a+b).
If you're asking if there's a single operator to prepend strings (instead of appending them like +=), I don't think there is one. Writing out:
b = a + b
is the most succinct way I know of how to prepend a onto b.
(Interestingly, because string appending is non-commutative, Larry Wall (the creator of Perl) chose to use . as the string-appending operator, so as to leave + completely commutative and mathematical, in that a += b means both a = a+b and a = b+a. Unless you explicitly overload it, of course.)
Short answer is no.
The long answer:
You can create your own class based on str and override some operator action.
class A(str):
def __add__(s, st):
return st + s
This one will work as:
>>> A(50)
'50'
>>> A(50) + 'abc'
'abc50'
>>> a = A('aaa')
>>> a += 'ccc'
>>> a
'cccaaa'
But you definitely will need to learn documentation about overriding "magic" methods such as __add__ to be sure that you'll implement right behavior, because there is many side-cases in which it could work not ideal in current implementation. For example, current implementation causes RecursionError if both sides is instances of A class.
Honestly, all this stuff is not very good practice because it's not about Zen of Python and may be cause of headache of other programmers that will work with this code. So all these things is nothing but interesting just for fun experiments. For real convenient solution see short answer.
P.S.: Of course, you can override some other operator instead of +. For example, __mul__ is for *. You can even override bitwise ops such as << and &
P.P.S.: The operator that you mentioned, %=, really exists. Not much people know about it, but it is a shorthand for a = a % b, it's very useful for formatting strings:
a = 'Some number: %d; some string: %s'
a %= 1, 'abc'
print(a)
Will give you Some number: 1; some string: abc
No, there is no such operation. The complete list of operators can be found in the Python language reference, starting at section 6.5.
You could define another class inheriting from str:
class myStr(str):
def __init__(self, s):
super(str, s)
def __add__(self, other):
return other + self
s = myStr("abc")
print(s) #prints 'abc'
s += "d"
print(s) #prints 'dabc'
I don't see any use case frankly, though.
Short answer is no. Read here. The += is called augmented assignment
It is implemented for the common binary operators in python:"+=" | "-=" | "*=" | "#=" | "/=" | "//=" | "%=" | "**="| ">>=" | "<<=" | "&=" | "^=" | "|="
You can change the workings of the augmented assignment operation by changing the way the operation is computed at class level, e.g. in your example:
class Foo(str):
def __add__(s, other):
return other + s
Although I would not recommend it.

How can we define a function without using the `def` keyword?

It's possible to define a class without using the class keyword.
The following ...
get_i = lambda self: self.i
get_i.__name__ = 'get_i'
get_i.__qualname__ = 'Klass2.get_i'
dct = dict(a=1, i=4, get_i=get_i)
Klass2 = type('Klass2', (SuperK,), dct)
... produces the same end result as:
class Klass1(SuperK):
a = 1
i = 4
def get_i(self):
return self.i
How can we do something similar for functions? That is, how can we define a function without using the def or lambda keywords? What might a pure-python implementation of dehf look like if the following two pieces of code created identical foos?
def foo(bar):
bar += 934
return bar
foo = dehf(blah, blah, blah, blah, [...])
You can create functions by calling the types.FunctionType constructor. Keep in mind however that this constructor is undocumented and implementation specific. In CPython, we can figure out the constructor arguments by calling help(types.FunctionType):
class function(object)
| function(code, globals[, name[, argdefs[, closure]]])
|
| Create a function object from a code object and a dictionary.
| The optional name string overrides the name from the code object.
| The optional argdefs tuple specifies the default argument values.
| The optional closure tuple supplies the bindings for free variables.
To create a code object, we can use compile:
code = compile('print(5)', 'foo.py', 'exec')
function = types.FunctionType(code, globals())
function() # output: 5

Python style decorator in Scala

In Python I can do something like this:
def wrap(f):
def wrapper(*args, **kwargs):
print "args: ", args, kwargs
res = f(*args, **kwargs)
print "result: ", res
return res
return wrapper
This lets me wrap any function regardless of the arguments they take. For instance:
In [8]: def f(thing):
print "in f:", thing
return 3
In [9]: wrapped_f = wrap(f)
In [10]: wrapped_f(2)
args: (2,) {}
in f: 2
result: 3
Out[10]: 3
Is there a way to do something similar (write a wrapper that can be applied to any function regardless of its input/output types) in Scala?
You could certainly do this with macros. You can convert a method call to a function with partial application:
object Foo {
def bar(i: Int): Int = i + 1
}
val fn = Foo.bar _
defined object Foo
fn: Int => Int = <function1>
Now you have an object, in this case of type Function1[Int, Int], which you can pass to a Scala macro, which would be something like this (not tested):
object DecoratorMacros {
import reflect.macros.blackbox
import language.experimental.macros
def decorate[A <: Function](fn: A): [A] = macro decorate_impl[A]
def decorate_impl[A: c.WeakTypeTag](c: blackbox.Context) = {
import c.universe._
val type = weakTypeOf[A]
...
}
}
In the body of the macro, you can inspect the whole type signature of fn: A, which will include the arguments. You can then write code to do your desired side effects, and return a function which you can then invoke. Something like this:
DecoratorMacros.decorate(Foo.bar _)(42)
Macros are fairly involved, but I can elaborate if you think this is a path you'd like to go down.
There is a fundamental issue here: in Scala you have to know what arguments the function should get and actually pass them so that the compiler can be sure that the types match.
Say there is def f(a: List[Int], b: String) = ... and def g(args: Any*) = f(args). This won't compile! (Any* means any amount of objects with any type). The problem is that Any* is still only one single argument which actually is translated to one kind of Array.
Just to make this more clear you could think of an example situation: you have called the wrap(f) with some function f(a: String, b: String). Then you have the output of the wrapper which would somehow accept any amount of any kind of arguments and you make the call wrapper_f(List(1), "a"). In this situation the wrapper_f(...) call should be correct but inside the wrapper the wrapped function has a completely different parameter list which can not accept a List[Int] and a String. Thus you would get the "Type Error" in runtime which should (in general) be impossible in statically typed programming languages (or at least in Scala).

String output modifiers in Python

In C++, objects can be output by "left-shifting" them to cout. They can be preceded by modifiers that change the output:
// print 2 numbers 'a' and 'b' in 0xAAAABBBB (hex) format
cout << "0x" << hex << uppercase << setw(4) << setfill('0') << a
(Source)
I'm looking for something similar in Python: I have a class for which I want two different possible outputs: it's something containing a float which I want to output either as a normal float or as a fraction. Currently, I'm passing a use_fractions flag in the constructor and have an if use_fractions: ... else: ... conditional in the __str__ and __repr__ members. But I find that logically flawed: the output format isn't some intrinsic property of the object, so I don't want to pass it to the constructor.
So my question is, is there any sort of modifier to __str__ comparable to the C++ example above? Something like a "contextual" parameter that can be set, and whose state I can check within __str__?
In Python, you'd use string formatting with str.format() or format(), which delegates handling of the actual formatting to a .__format__() special method.
The special method is passed the actual format spec; you can use anything you like there:
>>> class Foo(object):
... def __format__(self, spec):
... if spec == 'f':
... return 'fractions used'
... else:
... return 'decimals used'
...
>>> format(Foo(), 'f')
'fractions used'
>>> format(Foo(), 'g')
'decimals used'
The datetime.datetime() type uses this to support full strptime formatting, for example:
>>> from datetime import datetime
>>> format(datetime.now(), '%Y')
'2014'
You could do something like this:
class StringState():
fraction = False
class SetFraction():
def __str__(self):
StringState.fraction = True
return ""
class UnsetFraction():
def __str__(self):
StringState.fraction = False
return ""
class Test():
def __init__(self):
self.value = 0.05
def __str__(self):
if StringState.fraction:
return "1/20"
else:
return "0.05"
print Test(),'\n',SetFraction(),Test(),'\n',UnsetFraction(),Test()
Output:
0.05
1/20
0.05
I don't think there's any way to attach state to print itself, but if you use your own separate class, and then reference it in your print statements, you can achieve the same effect. There's probably a way to avoid the ugly spaces too.

automatic wrapper that adds an output to a function

[I am using python 2.7]
I wanted to make a little wrapper function that add one output to a function. Something like:
def add_output(fct, value):
return lambda *args, **kargs: (fct(*args,**kargs),value)
Example of use:
def f(a): return a+1
g = add_output(f,42)
print g(12) # print: (13,42)
This is the expected results, but it does not work if the function given to add_ouput return more than one output (nor if it returns no output). In this case, the wrapped function will return two outputs, one contains all the output of the initial function (or None if it returns no output), and one with the added output:
def f1(a): return a,a+1
def f2(a): pass
g1 = add_output(f1,42)
g2 = add_output(f2,42)
print g1(12) # print: ((12,13),42) instead of (12,13,42)
print g2(12) # print: (None,42) instead of 42
I can see this is related to the impossibility to distinguish between one output of type tuple and several output. But this is disappointing not to be able to do something so simple with a dynamic language like python...
Does anyone have an idea on a way to achieve this automatically and nicely enough, or am I in a dead-end ?
Note:
In case this change anything, my real purpose is doing some wrapping of class (instance) method, to looks like function (for workflow stuff). However it is require to add self in the output (in case its content is changed):
class C(object):
def f(self): return 'foo','bar'
def wrap(method):
return lambda self, *args, **kargs: (self,method(self,*args,**kargs))
f = wrap(C.f)
c = C()
f(c) # returns (c,('foo','bar')) instead of (c,'foo','bar')
I am working with python 2.7, so I a want solution with this version or else I abandon the idea. I am still interested (and maybe futur readers) by comments about this issue for python 3 though.
Your add_output() function is what is called a decorator in Python. Regardless, you can use one of the collections module's ABCs (Abstract Base Classes) to distinguish between different results from the function being wrapped. For example:
import collections
def add_output(fct, value):
def wrapped(*args, **kwargs):
result = fct(*args, **kwargs)
if isinstance(result, collections.Sequence):
return tuple(result) + (value,)
elif result is None:
return value
else: # non-None and non-sequence
return (result, value)
return wrapped
def f1(a): return a,a+1
def f2(a): pass
g1 = add_output(f1, 42)
g2 = add_output(f2, 42)
print g1(12) # -> (12,13,42)
print g2(12) # -> 42
Depending of what sort of functions you plan on decorating, you might need to use the collections.Iterable ABC instead of, or in addition to, collections.Sequence.

Categories