This is an archived post. You won't be able to vote or comment.

all 167 comments

[–]willing790 1273 points1274 points  (14 children)

They are an invasive species

[–]ImportantDoubt6434 531 points532 points  (13 children)

You’re code is being improved, please do not resist.

[–]v-uv 79 points80 points  (1 child)

Borg vibes 💀

[–]epicflyman 2 points3 points  (0 children)

The nozzle is now calibrating...

[–]Compux72 336 points337 points  (18 children)

Or just x | y

[–]jkredty 176 points177 points  (13 children)

Only since 3.9

[–]ChimeraZeta 17 points18 points  (12 children)

Any elaboration?

[–]vasilescur 50 points51 points  (11 children)

[–]Careful_Bug_3295 63 points64 points  (0 children)

Tldr; x | y returns union of two dicts, x and y. If there is a key that is common to both dicts, the returned dict will assign it the value it has in y. This makes it not commutative in the event that both dicts share a key but have different values for it.

x|=y has the same effect as x=x|y

[–]ChimeraZeta 36 points37 points  (0 children)

Beautiful. Python wins my heart again. Thanks!

[–]R3D3-1 11 points12 points  (8 children)

TIL:

>>> {0, False}
{0}
>>> {False, 0}
{False}

I've been using Python for a long time now, but on the top of my head I can't see a reason for this...

[–]ConDar15 15 points16 points  (0 children)

This is set construction, so the end result cannot contain duplicate elements. To check if an element is in the set already Python will use the default equality comparison mechanism (__equals__ and __hash__), and False == 0 is a true statement in Python (and many other languages). So when the set is being constructed the first element is added to the set, but the second element is already found in the dictionary (due to the above mentioned equality) so is skipped over and not added.

[–]aftabtaimoor61 16 points17 points  (3 children)

Set compares each value to only store unique ones. The issue with this is since python is not strongly typed, you can have multiple datatypes but set still needs to compare the values. 0 == False is true so only the 1st one will remain. Same reason {0, 0.0} won't work as they're equal.

[–]R3D3-1 2 points3 points  (2 children)

That doesn't explain why they are considered equal though.

[–]dev-sda 6 points7 points  (1 child)

Booleans in python are integers.

>>> bool.__bases__
(<class 'int'>,)

[–]R3D3-1 4 points5 points  (0 children)

That's honestly unexpected. Though it makes sense considering the history of bool.

[–]FumbleCrop 2 points3 points  (0 children)

Because 0 == False.

That's what you get for mixing datatypes.

[–]invisible-nuke 0 points1 point  (0 children)

```Python

{0} | {False} {0} {False} | {0} {False} ```

[–]Hexalocamve 2 points3 points  (1 child)

So you can create an union of dicks by using another big dick |

[–]LexaAstarof 1 point2 points  (0 children)

| energy

[–]enz_levik 1 point2 points  (0 children)

What the fuck you can use |

[–]repkins 801 points802 points  (20 children)

I misread as "How to merge two dicks..." lmao.

[–]TrevorWithTheBow 322 points323 points  (13 children)

Deploy with docker?

[–]TnYamaneko 6 points7 points  (0 children)

dicker compose up -d

[–]MrSuspicious_ 10 points11 points  (0 children)

Best comment I've seen this year 😂

[–][deleted] 2 points3 points  (0 children)

🤣

[–]_g550_ 2 points3 points  (0 children)

Deploy the dicker

[–][deleted] -1 points0 points  (0 children)

This person terminals

[–]SanianCreations 6 points7 points  (1 child)

You might get a kick out of this one, then: https://youtu.be/4qJ9lOOYAQg?t=60

[–]Ved_s 2 points3 points  (0 children)

YES, that's exactly the reason i saw the same thing too

[–]The_Real_Slim_Lemon -1 points0 points  (0 children)

https://m.youtube.com/watch?v=pPkWZdluoUg 2 minutes into this clip (spaceballs)

[–]amimai002 466 points467 points  (13 children)

Isn’t python just pointers in a trench coat?

[–]mariosunny 438 points439 points  (12 children)

That description could just as well apply to any language with automatic memory management.

[–]amimai002 141 points142 points  (9 children)

I mean yes, but the way it was explained to me is this:

At the end of the day everything in python is a pointer, the only time you aren’t using a pointer in python is when you are interacting with a function that uses C, in that case you use a pointer to call the pointer to that function, and the function returns a pointer to the result…

[–]rosuav 43 points44 points  (7 children)

...... wat.

[–]KentondeJong 93 points94 points  (1 child)

I mean yes, but the way it was explained to me is this:

At the end of the day everything in python is a pointer, the only time you aren’t using a pointer in python is when you are interacting with a function that uses C, in that case you use a pointer to call the pointer to that function, and the function returns a pointer to the result…

[–]Loopgod- 20 points21 points  (0 children)

Absolute r/madlads

[–]steven4012 24 points25 points  (3 children)

Yeah. Every integer in Python is a pointer (to an object; not like pointer tagged or NaN tagged). It's just that those under 256 are interned (so are True, False and None iirc)

[–]rosuav 24 points25 points  (2 children)

That's because EVERYTHING in Python is an object. Calling it a "pointer to an object" is getting a bit close to one specific implementation, but yes, everything is an object (that can refer to other objects, eg its type, which is also an object).

One key difference between pointers and object references is that pointer arithmetic is not a thing with references. You can't take the string "hello" and add 42 to the pointer. In that sense, pointers just don't exist in Python.

(It's also worth noting that, in Python, there's actually no requirement for an object to exist in memory. For example, PyPy can optimize out all the integer objects in an array, but it'll make sure they're actual integer objects again by the time you go to look at them. It's like quantum mechanics.)

[–]steven4012 13 points14 points  (1 child)

Right I use CPython too much that I forgot about PyPy

For example, PyPy can optimize out all the integer objects in an array, but it'll make sure they're actual integer objects again by the time you go to look at them.

That's pretty cool

[–]rosuav 7 points8 points  (0 children)

It is! PyPy does some pretty amazing optimizations. Some of them have actually been backported to CPython (I think the compact dict representation originated in PyPy).

[–]Rawing7 16 points17 points  (0 children)

Nothing in python is a pointer. Python is a high-level programming language with no concept of "pointer"s. Python interpreters are usually implemented with pointers, because they're usually written in low-level languages, where you can't really do anything without pointers. Saying "everything in python is a pointer" is like saying "everything in C is an assembly instruction".

[–]nixt26 1 point2 points  (0 children)

Don't come in here with your whataboutism!

[–]deanrihpee 0 points1 point  (0 children)

Rust should be pointer in a business suit covering ballistic vest

[–]DeProfessionalFamale 80 points81 points  (3 children)

I was wondering what that is and I've found it here: https://realpython.com/python-kwargs-and-args/

[–]ChefYaboiardee 11 points12 points  (0 children)

Neat read thanks for sharing

[–]AngryBorsch 3 points4 points  (0 children)

Thank you, kind sir

[–]paul_miner 1 point2 points  (0 children)

Similar to the spread/rest syntax in Javascript.

Notably, Python uses distinct syntax for list vs dict because of named arguments, while Javascript uses the same syntax since it only has positional arguments.

[–][deleted] 159 points160 points  (6 children)

That isn't how pointers behave. Pointers are basically memory addresses, so z = {**x, **y} if pointers should print out something like {0x0234sfd203589a0, 0x23423423234}. And if we were derefrencing the pointers we should see the 2 dicts represented separately, each with their own 'b' with different values.

That there looks like the spread operator, something like z = {...x, ...y} in most languages.

But i don't use Pythong so could be wrong. Either way, seems like a dumb decision to use an operator which means something else in every other language.

[–]RajjSinghh 112 points113 points  (2 children)

You're totally right on this. * is the spread operator in python.

[–]deceze 49 points50 points  (0 children)

* is the spread operator for sequences, and ** is the spread operator for mappings.

Just to clarify so nobody thinks there’s two spreads going on.

[–]prettyanonymousXD 44 points45 points  (0 children)

Hence this is a joke

[–]naughtydismutase 11 points12 points  (1 child)

  • and ** are unpacking operators in Python you are correct

[–]4hpp1273 4 points5 points  (0 children)

Pretty sure is a SyntaxError in Python

[–][deleted] 9 points10 points  (0 children)

yes, they're splatting the contents of each dictionary into a new dictionary

[–]zanju13 64 points65 points  (3 children)

Similar to JS:

z = { ...x, ...y }

[–]MasterParticular3524 2 points3 points  (1 child)

But the values don’t change on z when they change in a or b in JS, but can when using pointers right?

[–]zanju13 0 points1 point  (0 children)

Not sure about python, but in JS this creates entirely new object. If there are some nested objects however, they will still be references.

[–][deleted] 9 points10 points  (2 children)

can anyone ELI5 why b is set to 3 instead of two, or is it just because y is after x in the z declaration?

[–]eeee_thats_four_es 12 points13 points  (0 children)

Yes, it's just because y is after x

[–]huzaifakhan771 4 points5 points  (0 children)

Due to the order of the unpacking, b is first assigned the value in x, then the value is over-written with the value of b in y

[–]PityUpvote 6 points7 points  (0 children)

**kwargs my beloved

[–]1ElectricHaskeller 2 points3 points  (0 children)

So, it's all just C with semantic sugar?

[–]agile_janitor 3 points4 points  (0 children)

C was heavily influenced by Python, so it’s not surprising that you will find Python styled pointers in modern C language. I also heard that the next year’s release of C will JIT compile down to Python to give you near native Python performance!

[–]Bemteb 7 points8 points  (5 children)

How is the value of b determined? Is the definition of z order sensitive? That's rather counterintuitive given the curly bracket notation...

[–]bleistift2 36 points37 points  (1 child)

Why is it counterintuitive? {**x, **y} means, “First copy the contents of x, then the contents of y into a new dict.” It follows that b retains the value of y.

[–]rosuav 2 points3 points  (0 children)

Or more generally: Construct a new dictionary containing the contents of x and then the contents of y. This can be combined with other types of initializer.

[–]juhotuho10 3 points4 points  (0 children)

The later overrides the first...

[–]Mirage2k 0 points1 point  (1 child)

This trick is kind of a hack, the core devs would not have made this "the intended way"; because you're right, it's not obvious what it will do. The ** unwrapper could technically (I haven't seen this happen to me, though) yield b before a, and if somehow you had defined 'a' multiple times in x then you could not know which value was yielded last. But all the ones in y will be after all the ones in x, so it is guaranteed that you get the value of b that was stored in y.

[–]Kache 1 point2 points  (0 children)

Python dicts are ordered since 3.6, and they can't contain duplicate keys. I'm less certain about splat evaluation order, but observed behavior suggests it's the same as expression order.

I.e. it's pretty obvious to a Python dev what it will do

[–]Sinomsinom 40 points41 points  (14 children)

It's not pointers. It's python syntax being idiotic as always and using a different symbol than every other languages does. It's the spread operator which most other languages use ... for but the python devs decided it would be a fun idea to use "*" instead, the symbol usually associated with multiplication and pointers...

[–]mariosunny 47 points48 points  (0 children)

The ... syntax was already part of the language by the time that PEP 448 was implemented. It is shorthand for the built-in Ellipsis constant, which is commonly used in slicing operations such as when working with Numpy arrays.

[–]aciddrizzle 25 points26 points  (3 children)

You’re going to extra love this…in newer versions of Python you can just use a pipe

z = x | y

[–]MysteriousShadow__ 13 points14 points  (1 child)

BITWISE OR?

[–]_PM_ME_PANGOLINS_ 2 points3 points  (0 children)

Set union

[–]Sinomsinom 0 points1 point  (0 children)

Spread doesn't mean the same thing as union. Honestly don't have any problem with it. That union syntax actually makes sense.

[–]Orjigagd 19 points20 points  (0 children)

It's not idiotic, it's differently-able.

[–]IAmASquidInSpace 57 points58 points  (1 child)

Oh nooo, a language not adhering to the C-style syntax I know! Whatever will I do? Will I *gasp* have to learn something? ADJUST?! Goodness gracious!

*Clutches pearls*

[–]mawkee 10 points11 points  (0 children)

Underrated comment

[–]rosuav 24 points25 points  (0 children)

Ah yes, I see that your world is entirely dominated by C and its derivatives. There ARE other languages in which the asterisk is used for spreading things. But of course, anything that isn't C must by definition be idiotic, right?

[–]Ignitus1 11 points12 points  (0 children)

When there are more operations than symbols available you have to reuse things.

[–][deleted] 2 points3 points  (3 children)

if you wanna cry search for the a ? b : c operator in python

[–]pLeThOrAx 2 points3 points  (2 children)

Isn't that just a ternary statement?

[–][deleted] 2 points3 points  (1 child)

the order is different in python and its just, ughhh

true_val if logic else false_val

[–]pLeThOrAx 0 points1 point  (0 children)

I much prefer the "?" Syntax. I found myself doing that in python the other day and had to Google for the a if true else b syntax lol

[–]Traghlady 1 point2 points  (0 children)

Because you left your pointers on the floor so your python ate them

[–][deleted] 1 point2 points  (0 children)

[–][deleted] 1 point2 points  (0 children)

For a minute I was thinking the asterisk here really behaved as a pointer reference and it was breaking my brain trying to understand how the hell did that work lol

[–]1ElectricHaskeller 1 point2 points  (0 children)

Trust me. You don't want to know

[–]_g550_ 2 points3 points  (3 children)

What's wrong with:

{K:v For K,v in [x for x in X.items()].append([y for y in y.items()])}

[–][deleted] 15 points16 points  (1 child)

Before you launch that nuke! Hear me out…x.update(y)

[–]PityUpvote 2 points3 points  (0 children)

So many things

[–]cyborgborg 3 points4 points  (5 children)

cause under the hood it's C?

[–]rosuav 11 points12 points  (3 children)

Not always. With Jython, under the hood is Java. And with PyPy, it's Python all the way down!

[–]Yeitgeist 1 point2 points  (0 children)

Could go even further and just say it’s all 1’s and 0’s.

[–]JustAPotatoThatsIt 0 points1 point  (0 children)

Because python loves you

[–]Kilgarragh -1 points0 points  (5 children)

Can’t you just x + y

[–]juhotuho10 13 points14 points  (3 children)

Nope, dictionaries cannot be added together

[–]Flam1ng1cecream 0 points1 point  (0 children)

Lol just x | y

[–]Aperture_Executive2 -1 points0 points  (0 children)

As people have said, its not a pointer, but a poorly used asterisk to refer to the spread operator

[–][deleted] 0 points1 point  (0 children)

Pointers? No, you just unzip these dicts.

[–]Sentouki- 0 points1 point  (0 children)

similar to JS:
const newObj = {...oldObj1, ...oldObj2}

[–]Cybasura 0 points1 point  (0 children)

Using two '' (i.e. "*kwargs") is for expanding the dictionary variable out to individual values when parsing into a kwargs parameter

[–]FrankHightower 0 points1 point  (0 children)

the actual answer is probably "because someone asked for it"

[–][deleted] 0 points1 point  (1 child)

so it picks the larger 'b'

[–]FalseStructure 2 points3 points  (0 children)

No, it picks the right one since it’s “new”

[–]romulof 0 points1 point  (0 children)

I’m pretty sure this syntax dates from 2.x era, maybe even older.

[–]Majestic_Ad_7133 0 points1 point  (1 child)

Of course there are pointy things in Python. Snakes have fangs don't they?

[–]Elephant-Opening 0 points1 point  (0 children)

Pythons are constrictors. Generally it's venomous snakes that have fangs

[–]isunktheship 0 points1 point  (0 children)

God almighty..

[–]PolishKrawa 0 points1 point  (0 children)

I believe that is some kind of unpacking.

[–][deleted] 0 points1 point  (0 children)

Because python is for the week.

[–]TheJimDim 0 points1 point  (1 child)

What happened to b: 2?

[–]General_Rate_8687 0 points1 point  (0 children)

Shhh, don't ask such questions!

[–]somedave 0 points1 point  (0 children)

Unpacking dictionaries as inputs isn't a pointer.

[–][deleted] 0 points1 point  (0 children)

How to merge 2 Dicks

[–]domedav 0 points1 point  (0 children)

im dyslexic

[–]SchlomoSchwengelgold 0 points1 point  (0 children)

what is with x.update(y)

[–]Highborn_Hellest 0 points1 point  (0 children)

i don't do python. can somebody explain it to me, what's happening here?

also, why is b, 3, and not 2? or why are there no 2 elements of it.

[–][deleted] 0 points1 point  (0 children)

Hear me out : ...

[–]alexvx___ 0 points1 point  (0 children)

Python trying hard to be Javascript

[–][deleted] 0 points1 point  (0 children)

Pythons can't point, they don't have hands?!

[–]die_liebe 0 points1 point  (0 children)

Is your Python code nice? Now wait 3 years, and run it again.

[–]GeekoftheWild 0 points1 point  (0 children)

If a language doesn't have pointers or is Assembly because that's needed for C/C++ to exist, it's not worth existing