How to assign value inside list comprehension - python

How to assign a value to object's .ID attribute from [inside of a list comprehension]?
class C(object):
def __init__(self):
self.ID=0
l=[C() for i in range(4)]
print l
t=[c for c in l if c.ID+1]
for c in t: print c.ID,
[<main.C object at 0x10454de50>, <main.C object at
0x10454ded0>, <main.C object at 0x10454df90>, <main.C object
at 0x10455b150>]
0 0 0 0
[Finished in 0.1s]
edit
How to change i with list comprehension:
l=[i for i in range(4)]
i=0
t=[c for c in l if i++]
print i

You could define a simple function do perform the transformation:
def foo(c):
c.ID += 1
return c
Then use it in the list comprehension:
>>> t=[foo(c) for c in l]
>>> for c in t: print c.ID,
1 1 1 1
>>> for c in l: print c.ID,
1 1 1 1
Note that it may be a good idea to add an ID parameter to C's constructor, so you can construct C objects with any ID you want:
class C(object):
def __init__(self, ID=0):
self.ID=ID
Then
>>> a = [c(42) for _ in xrange(4)]
>>> b = [c(i) for i in xrange(4)]
>>> for c in a: print c.ID,
42 42 42 42
>>> for c in b: print c.ID,
>>> 0 1 2 3

Related

Object to pandas dataframe

I have a list of objects like in the test variable below:
#dataclasses.dataclass
class A:
a: float
b: float
c: float
#dataclasses.dataclass
class B:
prop: str
attr: List["A"]
test = [
B("z", [A('a', 'b', 'c'), A('d', 'l', 's')]),
B("a", [A('s', 'v', 'c')]),
]
And I want it to transform it into a pandas df like this:
prop a b c
0 z a b c
0 z d l s
1 a s v c
I can do it in several steps, but it seems unnecessary and inneficient as I'm going multiple times through the same data:
a = pd.DataFrame(
[obj.__dict__ for obj in test]
)
a
prop attr
0 z [A(a='a', b='b', c='c'), A(a='d', b='l', c='s')]
1 a [A(a='s', b='v', c='c')]
b = a.explode('attr')
b
prop attr
0 z A(a='a', b='b', c='c')
0 z A(a='d', b='l', c='s')
1 a A(a='s', b='v', c='c')
b[["a", "b", "c"]] = b.apply(lambda x: [x.attr.a, x.attr.b, x.attr.c], axis=1, result_type="expand")
b
prop attr a b c
0 z A(a='a', b='b', c='c') a b c
0 z A(a='d', b='l', c='s') d l s
1 a A(a='s', b='v', c='c') s v c
Can it be done a bit more efficient?
Use a combination of dataclasses.asdict and pd.json_normalize
In [59]: pd.json_normalize([dataclasses.asdict(k) for k in test], 'attr', ['prop'])
Out[59]:
a b c prop
0 a b c z
1 d l s z
2 s v c a
Another version:
df = pd.DataFrame({"prop": b.prop, **a.__dict__} for b in test for a in b.attr)
Result:
prop a b c
0 z a b c
1 z d l s
2 a s v c

How to get correct answer in for loop

I want to do multiplication using for loop. Here is the code.
a = 4
b = 6
for i in [a,b]:
i*=2
The values of a and b remain the same. How to make it work?
int are immutable, so you'll need to rebind a and b to fresh int objects
>>> a = 4
>>> b = 6
>>> a, b = (i*2 for i in [a,b])
>>> a
8
>>> b
12
Use dictionary:
z = {'i': a, 'j': b}
for k in z.keys():
z[k] *= 2
a = z['i']
b = z['j']

Parametrized generators?

I need parametrized generator. Such one that will accept parameters on the call to .next(arg).
In this specific case I want the generator to change with +1 when arg is True and -1 on False.
Is this possible in python ?
Using the .send method on a generator instance allows you to inject state into the generator. That makes something like this possible:
>>> def mygen():
... i = 0
... sign = 1
... while True:
... val = yield sign*i
... if val is not None:
... sign = 1 if val else -1
... i += 1
...
>>> g = mygen()
>>> next(g)
0
>>> next(g)
1
>>> next(g)
2
>>> g.send(False)
-3
>>> next(g)
-4
>>> next(g)
-5
>>> g.send(True)
6
>>> next(g)
7
Note that next(g) is equivalent to g.send(None).
Here is my final version :
def flip_flop(low=0, high=10):
i = 0
while i >= low and i <= high :
cond = yield i
if cond : i += 1
else : i -= 1
In [64]: ff = flip_flop()
In [65]: ff.next()
Out[65]: 0
In [66]: ff.send(True)
Out[66]: 1
In [67]: ff.send(True)
Out[67]: 2
In [68]: ff.send(True)
Out[68]: 3
In [69]: ff.send(False)
Out[69]: 2

Python (Fibo series): trying to understand what is the difference between a, b = b, a + b OR a = b & a = a + b

I am not sure what would be an appropriate heading for this question and this can be a repeated question as well. So please guide accordingly.
I am new to python programming. I have this simple code to generate Fibonacci series.
1: def fibo(n):
2: a = 0
3: b = 1
4: for x in range(n):
5: print (a, end=' ')
6: #a, b = b, a+b
7: a = b
8: b = a+b
9: print()
10: num = int(input("enter n value: "))
11: print(fibo(num))
If I execute the above code as-is the result I get is as follows
enter n value: 10
0 1 2 4 8 16 32 64 128 256
If uncomment #6 and comment lines #7 and #8 the result I get is the actual fibo series.
enter n value: 10
0 1 1 2 3 5 8 13 21 34
I would like to know what is the difference between
a, b = b, a + b
and
a = b
b = a + b
Programming IDE used: PyCharm Community 2017.3
a = b
b = a + b
is actually:
a = b
b = b + b
what you want is:
a = b
b = old_value_of_a + b
When you do
a, b = b, a + b
it really is doing:
tmp_a = b
tmp_b = a + b
a = tmp_a
b = tmp_b
which is what you want
In line 7, you've already assigned the value in b to a, so in line 8, new value for b is actually double the old b's value.
While in line 6, the values on the right side of = will be using the old values, that's why you could get Fibo series.
Assignment Statements assigns reference of source variable to target variable. Let walk through an example to understand more
>>> a = 5
>>> b = 6
>>> a = b
In this example b is source variable and a is the target variable. Now memory address for both of these variables are same. We can confirm this as well
>>> hex(id(a)), hex(id(b))
>>> ('0x1002739e0', '0x1002739e0')
Another test to confirm this is to use is operator
>>> a is b
>>> True
Now coming back to your example. First statement
>>> a, b = b, a + b
Assignes b to a and (a+b) to b. This happens as a single operation so both variables are different. We can apply above tests to confirm this
>>> a is b
>>> False
>>> hex(id(a)), hex(id(b))
>>> ('0x1002739e0', '0x2008739t0')
The second statement
>>> a = b
>>> b = a + b
Assignes b to a and then (a+b) to b. These are two different statements, so at first step a and b are already identical. Thus the second statement is equivalent to b = b + b.
Thought make it simple so anyone can understand it
if you use this kind of syntax
a = 10
b = 20
a = b
b = a+b
print (a)
print (b)
after initially assigning a = 10 it will be assigning a = 20 since python is dynamically typed language it will change the value of variable a from 10 to 20
so the result will be like
a=20
b=40
but if we use
a = 10
b = 20
a,b = b,a+b
print (a)
print (b)
this will be assigning the values in a single line so the values of a and b will be exactly used from what it is initialised above it and the result will be like
which is the correct solution
a=20
b=30
I think the # line is pythonic solution. But if you got confused,you can you use a variable which is temporary. you can assign the value temp before, then you can change the values

In line variables in Python 3

Can someone explain the difference between:
a, b = 0, 1
while b < 10:
print(b)
a, b = b, a+b
and
a, b = 0, 1
while b < 10:
print(b)
a = b
b = a+b
Simultaneous:
a = 1
b = 3
a, b = b, a+b
# a: 3; b: 1+3
Sequential:
a = 1
b = 3
a = b
# a: 3; b: 3
b = a+b
# a: 3; b: 3+3
The first one computes all the new values before updating a and b. The second one computes and updates a before computing and updating b. The second one will give incorrect results because of that.
Here's part of a good talk by Raymond Hettinger where he talks about updating multiple state variables at once.
It's a shorthand to avoid a temporary variable. In many traditional languages, you had to do
tmp = a
a = b
b = b + tmp

Categories

Resources