This question already has answers here:
What's the purpose of the + (pos) unary operator in Python?
(7 answers)
Closed 8 years ago.
I am writing a function computing like eval. When I come to float.__pos__ ,I really don't Know why there exists such a useless function. Because:
>>> float.__pos__(-1.0)
-1.0
>>> float.__pos__(1.0)
1.0
while float.__neg__ is totally different:
>>> float.__neg__(1.0)
-1.0
So what is the meaning of float.__pos__?
>>> help(float.__pos__)
Help on wrapper_descriptor:
__pos__(...)
x.__pos__() <==> +x
It's the "unary plus" operator, invoked when you do +x with x a float. It basically does nothing for floats, as you've discovered ;-) However, you could define a subclass that did something non-trivial with it. That's why it's there.
The __pos__ method defines the effect of the unary + operator for any object.
As Tim Peters mentions, it has no effect for floats.
See What's the purpose of the + (pos) unary operator in Python? for an example where it's used to do something.
Python has a unary negation operator to negate numbers, as you're probably well aware:
>>> x = 5
>>> print(-x)
-5
>>> x = -5
>>> print(-x)
5
Say you're making a list of numbers, though. It might be more consistent if you prefixed the positive ones with a +, so Python has a unary + operator, too:
>>> numbers = [-3, -2, -1, 0, +1, +2, +3]
When you use the unary + operator on a number, you're right that it doesn't do anything; it's there just for consistency.
Now when you consider that in Python you can override operators on types, of course you'd need a __neg__ to negate an instance of that type. Python just decided to be consistent by also having a __pos__ to…not negate an instance of that type. float, like all other types overriding these operators, follow this protocol, and float's implementation of __pos__ is just the identity function.
Related
What is the difference with inv and invert?
>>> import operator
>>> operator.inv is operator.invert
False
>>> operator.__inv__ is operator.__invert__
False
I gather that __invert__ is the hook for the unary ops like ~1 or (1).__invert__().
But what is the other one __inv__ corresponding to? Or if it's same, why we have another name and a different function added for doing same thing?
Both represent the same operator. The long spelling was added in Python 2.0, and the short spelling was never removed.
operator.inv(obj)
operator.invert(obj)
operator.__inv__(obj)
operator.__invert__(obj)
Return the bitwise inverse of the number obj.
This is equivalent to ~obj.
New in version 2.0: The names invert() and __invert__().
Source: Python 2 operator documentation.
These are implemented as different objects because their representation reflects the name. Note that the corresponding dunder and regular names do share the same representation and object.
>>> operator.__inv__
<built-in function inv>
>>> operator.__invert__
<built-in function invert>
>>> operator.__inv__ is operator.inv
True
>>> operator.__invert__ is operator.invert
True
Historically, both names were equally viable - the Python 1 operator module used the inv/__inv__ name, whereas the Python 1 data model used the special method __invert__ name.
I've been programming in Python for years but something extremely trivial has surprised me:
>>> -1 ** 2
-1
Of course, squaring any negative real number should produce a positive result. Probably Python's math is not completely broken. Let's look at how it parsed this expression:
>>> ast.dump(ast.parse('-1 ** 2').body[0])
Expr(
value=UnaryOp(
op=USub(),
operand=BinOp(
left=Num(n=1),
op=Pow(),
right=Num(n=2)
)
)
)
Ok, so it is treating it as if I had written -(1 ** 2). But why is the - prefix to 1 being treated as a separate unary subtraction operator, instead of the sign of the constant?
Note that the expression -1 is not parsed as the unary subtraction of the constant 1, but just the constant -1:
>>> ast.dump(ast.parse('-1').body[0])
Expr(
value=Num(n=-1)
)
The same goes for -1 * 2, even though it is syntactically nearly identical to the first expression.
>>> ast.dump(ast.parse('-1 * 2').body[0])
Expr(
value=BinOp(
left=Num(n=-1),
op=Mult(),
right=Num(n=2)
)
)
This behavior turns out to be common to many languages including perl, PHP, and Ruby.
It behaves just like the docs explain here:
2.4.4. Numeric literals
[...] Note that numeric literals do not include a sign; a phrase like -1 is actually an expression composed of the unary operator - and the literal 1.
and here:
6.5. The power operator
The power operator binds more tightly than unary operators on its
left; [...]
See also the precedence table from this part. Here is the relevant part from that table:
Operator | Description
-------------|---------------------------------
* | Multiplication, ...
+x, -x, ~x | Positive, negative, bitwise NOT
** | Exponentiation
This explains why the parse tree is different between the ** and * examples.
This question already has answers here:
Python string interning
(2 answers)
Are strings cached? [duplicate]
(1 answer)
About the changing id of an immutable string
(5 answers)
Closed 4 years ago.
I found a peculiar behavior while going through Python 3 data types especially string. If two strings a and b have the same value then a is b becomes True (Strings must not contain hyphen of course).
If:
>>> a = 'string_without_hyphen'
>>> b = 'string_without_hyphen'
Then:
>>> a is b
True
>>> a == b
True
But if:
>>> a = 'string-with-hyphen'
>>> b = 'string-with-hyphen'
Then,
>>> a is b
False
>>> a == b
True
which confused me.
Why is this happening?
Because moon rays and unicorns implementation details.
The is operator compares objects by identity, not by content.
The Python implementation you're using may or may not decide to reuse the same string object for both a and b, if it feels like it, since strings are immutable in Python. The same may or may not occur for integers (and in fact, this also happens with Java's Integers if they're sufficiently small).
The gist is: never use is unless you really do need identity (address) comparison; things may be weird. Use == instead.
I always though that using the "+" operator in Python (3.5) calls the __add__ method under the hood and return the sum. However, I noticed some quirky behavior when negative numbers are involved.
Naturally,
>>>-3 + 7
returns 4
But(!)
>>>-3 .__add__(7)
returns -10 and
>>>-3 .__add__(-7)
4
>>>3 .__add__(7)
10
Is there a reason why __add__ signs the arguments if the object is signed. Also, what changes in the method so that when I use "+", the "correct" value comes out?
- is an operator too, an unary one. You called __add__ on 3, not on the result of - applied to 3, because attribute access binds more tightly than the - operator.
Use parentheses:
>>> (-3).__add__(7)
4
Your code applies the - unary operator to the result of 3 + 7 instead.
.__add__ is an operation between two objects so 3.add(7) = 10;
-3.add(7) is like calling add for 3 and 7 and then applying (-) as an operator
So -(10) as a result
You need to use parentheses to get the proper operation
Is it possible in Python to calculate a term in a string?
For example:
string_a = "4 ** (3 - 2)"
unknown_function(string_a) = 4
Is this possible? Is there a function that mimics "unknown_function" in my example?
Just like sympy was a useful module for your last question, it can apply here:
>>> import sympy
>>> sympy.sympify("4**(3-2)")
4
and even
>>> sympy.sympify("2*x+y")
2*x + y
>>> sympy.sympify("2*x+y").subs(dict(x=2, y=3))
7
Note though that this will return sympy objects, and if you want to get an integer or a float out of it you should do the conversion explicitly:
>>> type(sympy.sympify("4**(3-2)"))
<class 'sympy.core.numbers.Integer'>
>>> int(sympy.sympify("4**(3-2)"))
4
I hacked together a recipe to turn string expressions into functions here which is kind of cute.
There is eval
eval(string_a)
# 4
But do not use this under any circumstances if string_a comes from anyone but you, because they can easily hack into your system and destroy your files!
Yes, you can use the eval function.
>>> string_a = "4 ** (3 - 2)"
>>> eval(string_a)
4
>>>
You can read more in the documentation
There is a module py-expression-eval, that does not depend on the use of eval. It can be used to evaluate strings as a mathematical expression, even symbolic expressions can be evaluated.
from py_expression_eval import Parser
parser = Parser()
expr = parser.parse("4 ^ (3 - 2)")
expr.evaluate({})
For the use with symbolic expressions see:https://axiacore.com/blog/mathematical-expression-evaluator-python/