Equivalent of python walrus operator (:=) in c++11? - python

Recently I have been using the := operator in python quite a bit, in this way:
if my_object := SomeClass.function_that_returns_object():
# do something with this object if it exists
print(my_object.some_attribute)
The question
Is there any way to do this in c++11 without the use of stdlib?
for example in an arduino sketch if I wanted to use a method that may potentially return zero, such as:
if(char * data = myFile.readBytes(data, dataLen))
{
// do something
}
else
{
// do something else
}

Python's := assignment expression operator (aka, the "walrus" operator) returns the value of an assignment.
C++'s = assignment operator (both copy assignment and move assignment, as well as other assignment operators) does essentially the same thing, but in a different way. The result of an assignment is a reference to the object that was assigned to, allowing that object to be evaluated in further expressions.
So, the equivalent of:
if my_object := SomeClass.function_that_returns_object():
# do something with this object if it exists
print(my_object.some_attribute)
Would be just like you showed:
SomeType *object;
if ((my_object = SomeClass.function_that_returns_object())) {
// do something with this object if it exists
print(my_object->some_attribute);
}
If function_that_returns_object() returns a null pointer, the if evaluates object as false, otherwise it evaluates as true. The same can be done with other types, eg:
int value;
if ((value = SomeClass.function_that_returns_int()) == 12345) {
// do something with this value if it matches
}

Not exactly, no.
As is mentioned in other answers, the c++ = operator already does most of what you want. If have an existing variable then assignment to that variable returns a reference to it, so you can put that into an if condition:
Foo* a_pointer;
if (a_pointer = some_function()) {
//...
}
Here, the body of the if conditional will execute if some_function return a non-null pointer and a_pointer will be a copy of the pointer returned by some_function.
Unlike the walrus operator though, this has the limitation that a_pointer had to first be defined outside of the if condition.
C++17 adds something a bit closer, in that you can initialize a variable inside of the if condition with a special if-initializer syntax:
if (Foo* a_pointer = some_function(); a_pointer) {
//...
}
Note that the initializer still doesn't directly contribute to the truthiness of the if condition. It's only the expression after the ; that determines if the body of the if statement will execute. In this case, a_pointer is initialized to be the value returned by some_function in the initializer and then the condition part checks if a_pointer is truthy.

According to the documentation, readBytes returns the number of bytes placed in the buffer (not a pointer), so I think you just need to do something like:
if(myFile.readBytes(data, dataLen))
{
// do something with data
}
else
{
// do something else
}

Related

operator.index with custom class instance

I have a simple class below,
class MyClass(int):
def __index__(self):
return 1
According to operator.index documentation,
operator.index(a)
Return a converted to an integer. Equivalent to a.__index__()
But when I use operator.index with MyClass instance, I got 100 instead of 1 (I am getting 1 if I use a.__index__()). Why is that?.
>>> a = MyClass(100)
>>>
>>> import operator
>>> print(operator.index(a))
100
>>> print(a.__index__())
1
This actually appears to be a deep-rooted issue in cpython. If you look at the source code for operator.py, you can see the definition of index:
def index(a):
"Same as a.__index__()."
return a.__index__()
So...why is it not equivalent? It's literally calling __index__. Well, at the bottom of the source, there's the culprit:
try:
from _operator import *
except ImportError:
pass
else:
from _operator import __doc__
It's overwriting the definitions with a native _operator module. In fact, if you comment this out (either by modifying the actual library or making your own fake operator.py* and importing that), it works. So, we can find the source code for the native _operator library, and look at the related part:
static PyObject *
_operator_index(PyObject *module, PyObject *a)
{
return PyNumber_Index(a);
}
So, it's a wrapper around the PyNumber_Index function. PyNumber_Index is a wrapper around _PyNumber_Index, so we can look at that:
PyObject *
_PyNumber_Index(PyObject *item)
{
PyObject *result = NULL;
if (item == NULL) {
return null_error();
}
if (PyLong_Check(item)) {
Py_INCREF(item);
return item;
}
if (!_PyIndex_Check(item)) {
PyErr_Format(PyExc_TypeError,
"'%.200s' object cannot be interpreted "
"as an integer", Py_TYPE(item)->tp_name);
return NULL;
}
result = Py_TYPE(item)->tp_as_number->nb_index(item);
if (!result || PyLong_CheckExact(result))
return result;
if (!PyLong_Check(result)) {
PyErr_Format(PyExc_TypeError,
"__index__ returned non-int (type %.200s)",
Py_TYPE(result)->tp_name);
Py_DECREF(result);
return NULL;
}
/* Issue #17576: warn if 'result' not of exact type int. */
if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
"__index__ returned non-int (type %.200s). "
"The ability to return an instance of a strict subclass of int "
"is deprecated, and may be removed in a future version of Python.",
Py_TYPE(result)->tp_name)) {
Py_DECREF(result);
return NULL;
}
return result;
}
PyObject *
PyNumber_Index(PyObject *item)
{
PyObject *result = _PyNumber_Index(item);
if (result != NULL && !PyLong_CheckExact(result)) {
Py_SETREF(result, _PyLong_Copy((PyLongObject *)result));
}
return result;
}
You can see before it even calls nb_index (the C name for __index__), it calls PyLong_Check on the argument, and if it's true, it just returns the item with no modification. PyLong_Check is a macro that checks for long subtyping (int in python is a PyLong):
#define PyLong_Check(op) \
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LONG_SUBCLASS)
#define PyLong_CheckExact(op) Py_IS_TYPE(op, &PyLong_Type)
So, basically, the takeaway is that for whatever reason, probably for speed, int subclasses don't get their __index__ method called, and instead just get _PyLong_Copy'd to the resulting return value, but only in the native _operator module, and not in the non-native operator.py. This conflict of implementation as well as inconsistency in documentation leads me to believe that this is an issue, either in the documentation or the implementation, and you may want to raise it as one.
It's likely a documentation and not an implementation issue, as cpython has a habit of sacrificing correctness for speed: (nan,) == (nan,) but nan != nan.
* You may have to name it something like fake_operator.py then import it with import fake_operator as operator
This is because your type is an int subclass. __index__ will not be used because the instance is already an integer. That much is by design, and unlikely to be considered a bug in CPython. PyPy behaves the same.
In _operator.c:
static PyObject *
_operator_index(PyObject *module, PyObject *a)
/*[clinic end generated code: output=d972b0764ac305fc input=6f54d50ea64a579c]*/
{
return PyNumber_Index(a);
}
Note that operator.py Python code is not used generally, this code is only a fallback in the case that compiled _operator module is not available. That explains why the result a.__index__() differs.
In abstract.c, cropped after the relevant PyLong_Check part:
/* Return an exact Python int from the object item.
Raise TypeError if the result is not an int
or if the object cannot be interpreted as an index.
*/
PyObject *
PyNumber_Index(PyObject *item)
{
PyObject *result = _PyNumber_Index(item);
if (result != NULL && !PyLong_CheckExact(result)) {
Py_SETREF(result, _PyLong_Copy((PyLongObject *)result));
}
return result;
}
...
/* Return a Python int from the object item.
Can return an instance of int subclass.
Raise TypeError if the result is not an int
or if the object cannot be interpreted as an index.
*/
PyObject *
_PyNumber_Index(PyObject *item)
{
PyObject *result = NULL;
if (item == NULL) {
return null_error();
}
if (PyLong_Check(item)) {
Py_INCREF(item);
return item; /* <---- short-circuited here */
}
...
}
The documentation for operator.index is inaccurate, so this may be considered a minor documentation issue:
>>> import operator
>>> operator.index.__doc__
'Same as a.__index__()'
So, why isn't __index__ considered for integers? The probable answer is found in PEP 357, under the discussion section titled Speed:
Implementation should not slow down Python because integers and long integers used as indexes will complete in the same number of instructions. The only change will be that what used to generate an error will now be acceptable.
We do not want to slow down the most common case for slicing with integers, having to check for an nb_index slot every time.
Update
This answer is incorrect; I misread the documentation. See Aplet123's answer instead. Tl;dr the problem is actually that the C implementation doesn't match the documentation and Python implementation. The C implementation is more like a if isinstance(a, int) else a.__index__().
To prove it, try defining MyClass.__int__(). The outcome will be the same.
Original answer
See the documentation for object.__index__():
object.__index__(self)
Called to implement operator.index(), and whenever Python needs to losslessly convert the numeric object to an integer object (such as in slicing, or in the built-in bin(), hex() and oct() functions). Presence of this method indicates that the numeric object is an integer type. Must return an integer.
If __int__(), __float__() and __complex__() are not defined then corresponding built-in functions int(), float() and complex() fall back to __index__().
(added bold)
a.__int__() exists, so its return value is used instead.
>>> a.__int__
<method-wrapper '__int__' of MyClass object at 0x7f2c5f0f4ec8>
>>> a.__int__()
100

Pass by reference vs Pass by assignment? C# vs Python

I am working concurrently in C# and in Python.
Is there a difference, in terms of what is being created in memory, between passing a reference type in C#, and passing (by assignment) in Python? It seems in either case, if the variable is changed* in the function, it is changed in the outside scope as well.
(*) of course in Python it must be mutable for this to occur. An immutable object cannot be changed - but that is another topic.
Are we basically just talking different terminology for the same process, or is there a conceptual difference to be learned here, in terms of the underlying mechanism in memory?
First, all arguments are passed by value by default in C#. This has nothing to do with the type being a reference type or a value type, both behave exactly the same way.
Now, the question is, what is a variable? A variable is a placeholder for a value, nothing more. When a variabe is passed by copy, a copy of the value is made.
And what is the value stored in a variable? Well, if the type of the variable is a reference type, the value is basically the memory address of the object its referencing. If its a value type, then the value is the objet itself.
So when you say:
It seems in either case, if the variable is changed* in the function, it is changed in the outside scope as well.
That is deeply wrong because you seem to me be mixing up the type of the argument with how it is passed along:
First example:
var a = new object();
Foo(a);
var isNull = ReferenceEquals(a, null); //false!
void Foo(object o) { o = null; }
Here, a refence typed variable a is passed by value, a copy is made and then inside Foo its reassigned to null. a doesn't care a copy is reasigned inside Foo, it will still point to the same object.
Things of course change if you pass the argument by reference:
var a = new object();
Foo(ref a);
var isNull = ReferenceEquals(a, null); //true!
void Foo(ref object o) { o = null; }
Now you are not making a copy of a named o, you are passing a itself with an alias named o.
Things behave exactly the same with value types:
var a = 1;
Foo(a);
var isNull = 1 == 0; //false!
void Foo(int i) { i = 0; }
And
var a = 1;
Foo(ref a);
var isNull = 1 == 0; //true!
void Foo(ref int i) { i = 0; }
The difference between value types and reference types when you pass it a long by value is due to what the value of the variable is. Like we said before, reference typed variables store the address, so even if you pass along a copy, the copy points to the same object, so any changes in the object are visible from both variables:
var ii = new List<int>();
Foo(ii);
var b = ii.Count == 1; //true!
void Foo(List<int> list) { list.Add(1); }
But with value types, the value is the object itself, so you are passing along a copy of the object, and you are therefore modifying a copy:
struct MutableStruct
{
public int I { get; set; }
}
var m = new mutableStruct();
Foo(m);
var b = m.I == 1; //false!
void Foo(MutableStruct mutableStruct) { mutableStruct.I = 1; }
Does this make things clearer?

Python "if" statement - if xpath is true

im trying to code in python (very new to it) and need to check if an xpath is there then variable = the xpath but if not variable = string.
An example is below
if tree.xpath('//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()') = true
$value = tree.xpath('//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()')
else
$value = ''
You should really start by doing the whole official tutorial before anything else, as it will anwser your question.
First point : Python objects all have a 'truth' value in a boolean context, which is defined by the object's type and actual value. For builtin types, all empty containers (lists, dicts, sets etc), the empty string, all numerical zeros and the None object are false, everything else is true. For non builtin types you'll have to check the package's documentation.
The builtin type bool will also tell you the boolean value of a given object, so all of the below tests are equivalent:
if myobj:
xxx
if bool(myobj):
xxx
if bool(myobj) == True:
xxx
BUT keep in mind that it doesn't imply that bool(myobj) is the same as myobj - the first one is the boolean value of your object, so the following is NOT equivalent (unless myobj is one of True, 1 or 1.0):
if myobj == True:
xxx
Now wrt/ your actual code snippet: it's not valid Python (bad indentation, invalid identifier $value, invalid use of the assignment operator =, missing : after the if and else statements, wrong capitalization for True...)
Assuming you meant:
# let's make this at least readable:
path = '//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()'
if tree.xpath(path) == True:
value = tree.xpath(path)
else:
value = ''
The obvious error is the explicit test against True (tree.xpath() doesn't return a boolean). You either have to explicitely cast the return of tree.xpath() to a boolean (which is quite verbose, totally useless and definitly unpythonic) or just let Python do the right thing by removing the == True part of your test.
As a side note: calling tree.xpath twice in a row with the same argument is a waste of processor cycle (both calls will return the same value), so use a variable instead - it will also make your code much more readable and maintainable. The Pythonic version of your code would look something like:
path = '//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()'
found = tree.xpath(path)
value = found if found else ''
or even more simply:
path = '//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()'
value = tree.xpath(path) or ''
since the or operator will not yield a boolean value but either the first of it's operand that has a true value or the last operand if none has a true value.
#No need to test == if value is bool. and you not check, you assign value with one =
if anything:
#Then do this
else:
#Do this

Python's equivalent of Ruby's ||=

To check if a variable exist, and if exits, use the original value, other wise, use the new value assigned.
In ruby, it's
var ||= var_new
How to write it in python?
PS:
I don't know the name of ||=, I simply can't search it in Bing.
I think there is some confusion from the people who aren't really sure what the conditional assignment operator (||=) does, and also some misunderstanding about how variables are spawned in Ruby.
Everyone should read this article on the subject. A TLDR quote:
A common misconception is that a ||= b is equivalent to a = a || b, but it behaves like a || a = b
In a = a || b, a is set to something by the statement on every run, whereas with a || a = b, a is only set if a is logically false (i.e. if it's nil or false) because || is 'short circuiting'. That is, if the left hand side of the || comparison is true, there's no need to check the right hand side.
And another very important note:
...a variable assignment, even if not run, immediately summons that variable into being.
# Ruby
x = 10 if 2 == 5
puts x
Even though the first line won't be run, x will exist on the second line and no exception will be raised.
This means that Ruby will absolutely ensure that there is a variable container for a value to be placed into before any righthand conditionals take place. ||= doesn't assign if a is not defined, it assigns if a is falsy (again, false or nil - nil being the default nothingness value in Ruby), whilst guaranteeing a is defined.
What does this mean for Python?
Well, if a is defined, the following:
# Ruby
a ||= 10
is actually equivalent to:
# Python
if not a:
a = 10
while the following:
# Either language
a = a or 10
is close, but it always assigns a value, whereas the previous examples do not.
And if a is not defined the whole operation is closer to:
# Python
a = None
if not a:
a = 10
Because a very explicit example of what a ||= 10 does when a is not defined would be:
# Ruby
if not defined? a
a = nil
end
if not a
a = 10
end
At the end of the day, the ||= operator is not completely translatable to Python in any kind of 'Pythonic' way, because of how it relies on the underlying variable spawning in Ruby.
There is no particularly elegant way in python, because it's not particularly elegant to get yourself into a situation where you don't know whether a variable is existing or not. However, this seems closest:
try:
var
except NameError:
var = var_new
I'm not familiar with the ||= operator in ruby, but from what you have described this block should have the correct behaviour. That is, we leave var bound as is if it was an already existing variable, and we set it to var_new otherwise.
This is approximately, and idiomatically, what you want:
var = var or var_new
Python's rules for variables that "don't exist" are quite strict; this will throw an exception if var has not been previously assigned. However, if var evaluates as falsey, it will receive the value of var_new.
I say this is "idiomatically what you want" because the idiomatic larger structure for this kind of thing, in Python, goes like so:
var1 = None
var2 = None
var3 = None
# ... code here that may or may not set var1 through var3 ...
var1 = var1 or "default1"
var2 = var2 or "default2"
var3 = var3 or "default3"
Note also that Python has a fairly broad notion of "falsey". This construct is only valid if var cannot have been assigned zero, False, or any object considered to be "empty" (e.g. "", [], {}...). If you really want it to trigger only on None you have to write the more verbose
var = var if var is not None else var_new
and, rather than do that, I would generally look for another way to solve the larger problem.
Finally, if you can structure your code like this instead...
var1 = "default1"
var2 = "default2"
var3 = "default3"
# ... code here that may or may not set var1 through var3 ...
... then you should, because it's shorter and less complicated that way, and the None vs falsey issue is completely avoided.
Not very safe however another option would be:
var = locals().get('var', var_new)
try: var
except NameError: var = var_new
or
var = locals().get('var', var_new)

Implementing nb_inplace_add results in returning a read-only buffer object

I'm writing an implementation of the in-place add operation. But, for some reason, I sometimes get a read-only buffer as result(while I'm adding a custom extension class and an integer...).
The relevant code is:
static PyObject *
ModPoly_InPlaceAdd(PyObject *self, PyObject *other)
{
if (!ModPoly_Check(self)) {
//Since it's in-place addition the control flow should never
// enter here(I suppose)
if (!ModPoly_Check(other)) {
PyErr_SetString(PyExc_TypeError, "Neither argument is a ModPolynomial.");
return NULL;
}
return ModPoly_InPlaceAdd(other, self);
} else {
if (!PyInt_Check(other) && !PyLong_Check(other)) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
}
ModPoly *Tself = (ModPoly *)self;
PyObject *tmp, *tmp2;
tmp = PyNumber_Add(Tself->ob_item[0], other);
tmp2 = PyNumber_Remainder(tmp, Tself->n_modulus);
Py_DECREF(tmp);
tmp = Tself->ob_item[0];
Tself->ob_item[0] = tmp2;
Py_DECREF(tmp);
return (PyObject *)Tself;
}
If instead of returning (PyObject*)Tself(or simply "self"), I raise an exception, the original object gets update correctly[checked using some printf]. If I use the Py_RETURN_NONE macro, it correctly turns the ModPoly into None (in the python side).
What am I doing wrong? I'm returning a pointer to a ModPoly object, how can this become a buffer? And I don't see any operation on those pointers.
example usage:
>>> from algebra import polynomials
>>> pol = polynomials.ModPolynomial(3,17)
>>> pol += 5
>>> pol
<read-only buffer ptr 0xf31420, size 4 at 0xe6faf0>
I've tried change the return line into:
printf("%d\n", (int)ModPoly_Check(self));
return self;
and it prints 1 when adding in-place (meaning that the value returned is of type ModPolynomial...)
According to the documentation, the inplace add operation for an object returns a new reference.
By returning self directly without calling Py_INCREF on it, your object will be freed while it is still referenced. If some other object is allocated the same piece of memory, those references would now give you the new object.

Categories

Resources