31

Is there a way to format with the new format syntax a string from a function call?

For example:

"my request url was {0.get_full_path()}".format(request)

So it calls the function get_full_path() function inside the string and not as a parameter in the format function.


EDIT

Here is another example that will probably show my frustration better, this is what I would like:

"{0.full_name()} {0.full_last_name()} and my nick name is {0.full_nick_name()}".format(user)

This is what I want to avoid:

"{0} and {1} and my nick name is {2}".format(user.full_name(), user.full_last_name(), user.full_nick_name())
13
  • 1
    No, you can't. What difference will it make though doing "my request url was {0}".format(request.get_full_path())? Commented Nov 5, 2013 at 18:31
  • 1
    what I want to avoid is something like this: "my request url was {0} and my post was {1}".format(request.get_full_path(), request.POST). I want to use the same object only once Commented Nov 5, 2013 at 18:32
  • 4
    What's bad about using the same object twice? Commented Nov 5, 2013 at 18:32
  • 1
    In fact, by doing it like you want, you're still using the same object twice. Commented Nov 5, 2013 at 18:33
  • 3
    @nealmcb thanks for commenting, what I was looking got implemented in python 3.6 which is very exciting. Commented Mar 22, 2017 at 22:27

5 Answers 5

20

Not sure if you can modify the object, but you could modify or wrap the object to make the functions properties. Then they would look like attributes, and you could do it as

class WrapperClass(originalRequest):
    @property
    def full_name(self):
        return super(WrapperClass, self).full_name()

"{0.full_name} {0.full_last_name} and my nick name is {0.full_nick_name}".format(user)

which IS legal.

Sign up to request clarification or add additional context in comments.

3 Comments

It also works with dicts. '{0[hello]}'.format({'hello':'world'}) results in 'world'.
Yes, this dict retrieval works out-of-the-box without having this WrapperClass, FYI
good to know (i thought that was added later), but the question was about calling functions, not really looking up dictionary items. literal string interpolation can do it though..
17

Python 3.6 adds literal string interpolation, which is written with an f prefix. See PEP 0498 -- Literal String Interpolation.

This allows one to write

>>> x = 'hello'
>>> s = f'{x}'
>>> print(s)
hello

It should be noted that these are not actual strings, but represent code that evaluates to a string each time. In the above example, s will be of type str, with value 'hello'. You can't pass an f-string around, since it will be evaluated to the result str before being used (unlike str.format, but like every other string literal modifier, such as r'hello', b'hello', '''hello'''). (PEP 501 -- General purpose string interpolation (currently deferred) suggests a string literal that will evaluate to an object which can take substitutions later.)

Comments

8

Python pre-3.6 did not directly support variable interpolation. This meant that it lacked certain functionality (namely, function calling in strings) which other languages supported.

So, there isn't really anything to say here other than no, you couldn't do that, pre-3.6. That's just not how Python's formatting syntax worked.

The best you had was this:

"my request url was {0}".format(request.get_full_path())

1 Comment

Just made an edit, is not about the request object really. I am almost certain you are right about this, I just would like another syntax option that I guess doesn't exists :(
1

What about this very weird thing?

"my request url was %s and my post was %s"\
    % (lambda r: (r.get_full_path(), r.POST))(request)

Explanation:

  1. Classic way of formatting
  2. Lambda function which takes a request and returns a tuple with what you want
  3. Call the lambda inline as arguments for your string.

I still prefer the way you're doing it.

If you want readability you can do this:

path, post = request.get_full_path(), request.POST
"my request url was {} and my post was {}".format(path, post)

3 Comments

Yea I think that's just not worth it heh. I am looking more for a syntax that is permited there, for example, to format a datetime you can do {:%Y} and it works.
I'm sorry that's all I got :) I don't think Python goes so far. Especially, it's not famous for its string interpolation/formatting anyways :/
I'll just leave the question open for a while, but my hopes are low on this one :(
1

So summary of methods would be

(base) [1]~ $ cat r.py
# user is dict:
user = {'full_name': 'dict joe'}
print('{0[full_name]}'.format(user))

# user is obj:
class user:
    @property
    def full_name(self):
        return 'attr joe'


print('{0.full_name}'.format(user()))


# Wrapper for arbitray values - as dict or by attr
class Getter:
    def __init__(self, src):
        self.src = src

    def __getitem__(self, k):
        return getattr(self.src, k, 'not found: %s' % k)

    __getattr__ = __getitem__


print('{0[foo]} - {0.full_name}'.format(Getter(user())))
(base) [1]~ $ python r.py
dict joe
attr joe
not found: foo - attr joe

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.