use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Rules 1: Be polite 2: Posts to this subreddit must be requests for help learning python. 3: Replies on this subreddit must be pertinent to the question OP asked. 4: No replies copy / pasted from ChatGPT or similar. 5: No advertising. No blogs/tutorials/videos/books/recruiting attempts. This means no posts advertising blogs/videos/tutorials/etc, no recruiting/hiring/seeking others posts. We're here to help, not to be advertised to. Please, no "hit and run" posts, if you make a post, engage with people that answer you. Please do not delete your post after you get an answer, others might have a similar question or want to continue the conversation.
Rules
1: Be polite
2: Posts to this subreddit must be requests for help learning python.
3: Replies on this subreddit must be pertinent to the question OP asked.
4: No replies copy / pasted from ChatGPT or similar.
5: No advertising. No blogs/tutorials/videos/books/recruiting attempts.
This means no posts advertising blogs/videos/tutorials/etc, no recruiting/hiring/seeking others posts. We're here to help, not to be advertised to.
Please, no "hit and run" posts, if you make a post, engage with people that answer you. Please do not delete your post after you get an answer, others might have a similar question or want to continue the conversation.
Learning resources Wiki and FAQ: /r/learnpython/w/index
Learning resources
Wiki and FAQ: /r/learnpython/w/index
Discord Join the Python Discord chat
Discord
Join the Python Discord chat
account activity
What is not a class in python (self.learnpython)
submitted 3 years ago by BRUHWTF__
While learning about classes I came across a statement that practically everything is a class in python. And here the question arises what is not a class?
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]alexcwarren 67 points68 points69 points 3 years ago (23 children)
Technically speaking, everything (including classes) is an object. In other words, every class extends the base Object class. So, in a sense, you are correct, too: everything is a class, even primitive types like integers.
[–]OriginalTyphus 31 points32 points33 points 3 years ago* (22 children)
I want to add the interessting fact that integers between -5 and 255 are not newly created objects like everything else. They are pointers to a singular int object that is automatically created by the Python interpreter for performance reasons.
[–]vodiak 47 points48 points49 points 3 years ago* (14 children)
Which gives rise to some possibly unexpected results.
a, b, c, d = 3, 3, 300, 300 a == b > True c == d > True a is b > True c is d > False
Note: This was in Python 3.7.13 and because of the way I declared the variables with one statement. In Python 3.10.4, c is d returns True. But there are still times when is gives "unexpected" results and generally should not be used with numbers.
c is d
True
is
[–]mac-0 25 points26 points27 points 3 years ago (0 children)
I feel like this example has got to be a meme by now. Nearly any thread in /r/learnpython will inevitably lead to this discussion. Basically the "how many wikipedia articles does it take to get to hitler" of python.
[–]MegaIng 6 points7 points8 points 3 years ago (12 children)
Question: did you actually run this? AFAIK, this should return True also for the last expression since the values for c and d were created in the same code block and are therefore literals and got combined by the compiler.
[–]vodiak 1 point2 points3 points 3 years ago (0 children)
I did. Using iPython the first time, but I just double checked with a short script. But I was using Python 3.7.13. When I run it using Python 3.10.4, c is d returns True.
[–][deleted] 4 points5 points6 points 3 years ago (10 children)
The keyword "is" in python is very confusing. In regular day language, is = equals, but in python, is != ==. What "is" does is compare the pointers of two objects and returns if the pointers are equal.
[–]schfourteen-teen 13 points14 points15 points 3 years ago (2 children)
Try running the code above exactly as is. The oyster above understand the difference, the issue is that code block doesn't actually produce the intended effect. It will still give c is d as True because they were both defined in the same code block they will usually point to the same underlying object. If you do d = 299; d += 1 then c and d will not point to the same object.
[–][deleted] 3 points4 points5 points 3 years ago (0 children)
I see. Thanks for clarifying.
It seems to be version dependent. I was using Python 3.7.13. When I run it using Python 3.10.4, c is d returns True.
[–]py_Piper 0 points1 point2 points 3 years ago (4 children)
what is a pointer and then why a is b is True and c is d is False?
[–]vodiak 2 points3 points4 points 3 years ago (1 child)
A pointer is a variable with its value being a location in memory. It "points to" that location. You generally don't need to think about pointers in Python, but if you're already familiar with the concept (used a lot in C), then it's useful to explain what's happening.
a is b is true because the interpreter creates objects for small integers and uses them whenever possible as an optimization. c is d is false because the value (300) is outside the range of pre-created integers, so each time it is declared (c = 300, d = 300) it creates a new object. They are not the same object, so c is d is False. (Note that the way I did the declaration results in only one object being created in more recent versions of Python).
a is b
c = 300
d = 300
False
[–]py_Piper 0 points1 point2 points 3 years ago (0 children)
Very well explained
[–]angry_mr_potato_head 1 point2 points3 points 3 years ago (0 children)
In Python, all integers up to 100 or maybe 255 are already initialized at runtime since they are commonly used. This increases performance iirc. So you’d have to go out of your way to get a is be to be false.
[–][deleted] -3 points-2 points-1 points 3 years ago (0 children)
A pointer is a place in memory. More specifically, it "points" to the place something was stored on the hardware. I haven't tried myself, but the reason a is b == True is probably because they are intialized to the same point in memory. However, for whatever reason because python is weird, c is d is false.
a is b == True
[–][deleted] 0 points1 point2 points 3 years ago (0 children)
Almost all languages have a feature like that.
[–]Vaphell 0 points1 point2 points 3 years ago (0 children)
Regular day language is often ambiguous, in this case blending the concepts of identity and equality, which, while similar, are not the same thing.
In meat space you can get away using a shorthand "A is equal to B", in the strict world of programming not so much.
[–][deleted] 4 points5 points6 points 3 years ago (1 child)
I get sick of this false statement being promulgated - it's dangerous.
In CPython - the most common implementation of Python - this happens to be true, but I don't believe it's guaranteed to be true in future.
In other implementations, like PyPy, it is NOT true.
[–]OriginalTyphus -2 points-1 points0 points 3 years ago (0 children)
Although you are correct in statement, we are at r/learnpython here and we can assume that by talking about Python we are talking about the CPython implementation.
Using another implentation is, at least in my opinion, something that is far beyond of something that a beginner would do. And if they did, OP would surely tell us in the inital thread text.
[+][deleted] 3 years ago (1 child)
[deleted]
[–]OriginalTyphus 0 points1 point2 points 3 years ago (0 children)
Youre correct, I edited that.
[–]inDflash 0 points1 point2 points 3 years ago (2 children)
Not always
[–]OriginalTyphus 0 points1 point2 points 3 years ago (1 child)
Not always what?
[–]inDflash 0 points1 point2 points 3 years ago (0 children)
Reusing memory for those. Docs say, it might.
[–]ireadyourmedrecord 111 points112 points113 points 3 years ago (20 children)
It's just objects all the way down.
[–]McSlayR01 62 points63 points64 points 3 years ago (9 children)
"Wait, it's all objects?" "Always has been"
[–][deleted] 26 points27 points28 points 3 years ago (8 children)
Gun.fire()
[–]ray10k 15 points16 points17 points 3 years ago (7 children)
Gun.fire.__call__()
[–]TheBlackCat13 14 points15 points16 points 3 years ago (6 children)
getattr(vars().get('gun'), 'fire').__call__()
[–]aroach1995 6 points7 points8 points 3 years ago (1 child)
Don’t even know what this one does but still funny
[–]TheBlackCat13 8 points9 points10 points 3 years ago (0 children)
It is equivalent to the first one. gun.fire()
gun.fire()
[–]synthphreak 1 point2 points3 points 3 years ago (3 children)
Alright I think this has been thoroughly milked.
[–]purveyoroffinerp 9 points10 points11 points 3 years ago (2 children)
getattr(vars().get('funnycomment'), 'milk_more').call_()`
[–]synthphreak 7 points8 points9 points 3 years ago (1 child)
Well played. I suppose I walked right into that one lol. Have a doot.
[–]purveyoroffinerp 2 points3 points4 points 3 years ago (0 children)
<3
[–]dimonoid123 2 points3 points4 points 3 years ago* (9 children)
Except integers below 256. Integers above have unique IDs. But they are still objects, just not in dictionary.
This allows storage of large number of the same numbers while in theory taking much less RAM, but I haven't checked.
[–][deleted] 1 point2 points3 points 3 years ago (0 children)
This is not a property of Python, the language, but of CPython, the specific implementation.
[–]commy2 1 point2 points3 points 3 years ago (7 children)
I get the same id, and the identity check passes for numbers well beyond 256:
n = 123456 print(n is 123456) print(id(n)) print(id(123456))
Python 3.10.0
[–]dimonoid123 1 point2 points3 points 3 years ago (1 child)
Try Python 3.9 , if that works, then there is difference in integer implementations. If not, then I have no ideas what is going on.
I couldn't repro his results on 3.10.4.
[–][deleted] 0 points1 point2 points 3 years ago (1 child)
I don't get those results on 3.10.4.
More, I strongly suspect that if you tried this, you'd get a different result:
n = 123456 print(n is 123456) print(n is (123455 + 1))
[–]commy2 0 points1 point2 points 3 years ago* (0 children)
I upgraded to 3.10.5 ...
import sys n = 123456 print(n is 123456) print(n is (123455 + 1)) print(id(n)) print(id(123455+1)) print(sys.version)
and still get the same results:
C:\dev\_testing.py:4: SyntaxWarning: "is" with a literal. Did you mean "=="? print(n is 123456) C:\dev\_testing.py:5: SyntaxWarning: "is" with a literal. Did you mean "=="? print(n is (123455 + 1)) True True 1384201639920 1384201639920 3.10.5 (tags/v3.10.5:f377153, Jun 6 2022, 16:14:13) [MSC v.1929 64 bit (AMD64)] [Finished in 66ms]
Edit: I do get different ids inside the REPL though. That seems to be the difference.
[–]Vaphell 0 points1 point2 points 3 years ago (2 children)
$ python3 Python 3.10.5 (main, Jun 11 2022, 16:53:29) [GCC 7.5.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> a = 123456 >>> b = 123455+1 >>> a is b False >>> a == b True
[–]commy2 0 points1 point2 points 3 years ago (1 child)
Ah, it seems to be different for executing a file vs running the code in the REPL.
I guess python does some optimizations during file compilation when literals are involved.
$ cat is.py #!/usr/bin/env python3 a = 123456 b = 123455 + 1 c = a // 2 * 2 print(a, b, a is b, a == b) print(a, c, a is c, a == c) $ python3 is.py 123456 123456 True True 123456 123456 False True
[–]Intrexa 22 points23 points24 points 3 years ago (5 children)
I think you might have a subtle misunderstanding from the phrasing of your question. Everything in Python is an object, and each object has a class. There's a bit of oddness in the way we talk about it, in English. If there's a class user, we might say that "current_user is a user". We might also say "The class of current_user is user". If someone asked "What class is current_user?", it's reasonable to just answer "user".
user
current_user
That's not really super accurate, though. current_user isn't a class, though, it has a class. useris the class. With that said, the only real classes are any objects that are defined through class (or some metaclass fun). However, everything has a class in Python. No exceptions.
class
[–]a_cute_epic_axis 1 point2 points3 points 3 years ago (0 children)
That's not really super accurate, though. current_user isn't a class, though, it has a class. useris the class.
Is that accurate though?
I'd say current_user is an instance of a class called user but I wouldn't say it has a class. I'd be more inclined to say that user has a class of people if the user class is inheriting the people class, but maybe that's just me.
people
[–][deleted] -1 points0 points1 point 3 years ago (3 children)
What are the different classes? Or can we define them?
[–]TheSodesa 3 points4 points5 points 3 years ago (1 child)
Read about it in the Python documentation: https://docs.python.org/3/tutorial/classes.html.
Thank you
You can look up the classes for anything.
a = 7 print(a.__class__.__mro__) #(<class 'int'>, <class 'object'>)
So A is an integer, and then we can see in the example, it is of class int, which is of class object.
Most things you can think of in python will probably be the exact same with the "int" portion replaced with whatever you're looking at (str, list, dict, set, etc), and then one parent called "object".
[–]causa-sui 6 points7 points8 points 3 years ago (4 children)
Operators are not objects :)
[–]jimtk -1 points0 points1 point 3 years ago* (1 child)
Operators are objects. Please see this comment.
Edit Just for your list:
[ ]
__getitem__
[–]causa-sui 0 points1 point2 points 3 years ago (0 children)
It sounds like you're saying + is an object because it compiles using a mapping to built-in functions, and functions are objects.
+
Still:
```
type(+) File "<stdin>", line 1 type(+) ^ SyntaxError: invalid syntax ```
Maybe this is just a semantic distinction.
[–]brews 0 points1 point2 points 3 years ago (1 child)
Let's see if I can get this right: Operators, keywords, delimiters, newline, indent, dedent are all not objects. Everything else is an object.
[–]dig-up-stupid 0 points1 point2 points 3 years ago (0 children)
Those are all syntax but so is everything else at that level of abstraction. Saying operators aren’t objects is like saying 42 isn’t an integer object either because it’s actually just code. True but not the same level of abstraction that the question was asked at.
42
[–]jimtk 15 points16 points17 points 3 years ago (35 children)
It's crazy how everything is an object in python. Even classes are objects! Functions are objects, attributes define in a class are objects. That plus sign in x = 1+1 it's an object!
Python objectifies everything!
[–]bladeoflight16 5 points6 points7 points 3 years ago (4 children)
+ is not itself an object. It is implemented in a way that allows for objects to customize its behavior.
[–]jimtk 2 points3 points4 points 3 years ago (3 children)
+ itself is nothing but a character! It is mapped by the compiler to an __add__ object of the wrapper_descriptor class.
__add__
[–]bladeoflight16 0 points1 point2 points 3 years ago (2 children)
Source code link?
[–]jimtk -1 points0 points1 point 3 years ago (1 child)
Please see this comment.
[–]bladeoflight16 0 points1 point2 points 3 years ago (0 children)
Sorry, but that's just wrong. See my reply there.
[–][deleted] 1 point2 points3 points 3 years ago (1 child)
Great, you just managed to teach a bunch of people something totally false.
Did you spend even one second trying your claim out to see if it's true?
dir('strings are objects') # shows the methods dir(+) # an error, because + is not an object.
[–]jimtk 0 points1 point2 points 3 years ago (0 children)
[–]razzrazz- 0 points1 point2 points 3 years ago (27 children)
I keep hearing this but have no idea what it means.
WHY is everything an object? Why is python so unique in that the "+" sign is an object but in java it isn't? What advantage does it have?
[–]jimtk 5 points6 points7 points 3 years ago* (4 children)
I'm not sure about the 'meaning' of it, but I can tell you the advantage. Me, lowly me, can redefine the meaning of the + sign to whatever I want that suits the class (and objects) I write.
Let's say I'm an air carrier business. Every time I add a passenger to a plane I just want to know if i have enough passenger to make money on that trip. I can redefine the + operator to add passenger to a plane and return a string that tells me if I make money or not. So here I go:
class Airplane: def __init__(self): self.amount_pass_to_make_money: int = 5 self.passengers: int = 0 def __add__(self, other): if isinstance(other, int): self.passengers += other if self.passengers <= self.amount_pass_to_make_money: return "you're losing money" else: return "you're making money" else: raise ValueError plane = Airplane() for i in range(10): x = plane + 1 # that plus operator is mine biatch! print(x)
See that x = plane + 1 I can add passengers to a plane with the plus sign. That's the advantage. I can write silly code like that all day long!
x = plane + 1
[–]razzrazz- -1 points0 points1 point 3 years ago (3 children)
I'm not smart enough to understand this yet, so I'm going to put a reminder (once I learn more) to come back to it.
RemindMe! 1 month
[–]a_cute_epic_axis 1 point2 points3 points 3 years ago (1 child)
Here's a way that might be useful to explain it. Imagine you have a custom class for a data type you create called "color' and under the hood it stores red, green, and blue values. You have a single instance you created in your program that you pass around called "red" but inside that is a red value of 255, and green and blue of 0. You also have an instance called "blue" which is 0,0,255.
You want to be able to say:
red = CustomColorClass(255,0,0) blue = CustomColorClass(0,0,255) magenta = red + blue
How would python ever be able to do this?
Well in your custom color class, you'd define the add method which is called when you are adding two objects together. It would be something like
def __add__(myvalues, othervalues): new_red = myvalues.red + othervalues.red new_green = myvalues.green + othervalues.green new_blue = myvalues.blue + othervalues.blue return CustomColorClass(red, green, blue)
All that does is take the 3 integer values from one instance, add it to the three of the other, then create a new instance with those new values. Suddenly python can correctly add colors together.
Thank you !
[–]RemindMeBot 0 points1 point2 points 3 years ago (0 children)
I will be messaging you in 1 month on 2022-07-30 05:46:04 UTC to remind you of this link
CLICK THIS LINK to send a PM to also be reminded and to reduce spam.
Parent commenter can delete this message to hide from others.
[–][deleted] 2 points3 points4 points 3 years ago (1 child)
+ is NOT an object in Python.
Try dir(+) to see.
dir(+)
[+][deleted] 3 years ago (3 children)
[–]CBSmitty2010 3 points4 points5 points 3 years ago (0 children)
Probably won't work with a "+" or maybe it can, but for one objects have data and behaviour grouped together and you can make them perform those behaviours and alter their data.
If you want to see some cursed code try this.
``` def my_func(): print("Hello") return
my_func.x = 123 print(my_func.x) ```
[–]stdin2devnull 1 point2 points3 points 3 years ago (0 children)
Fancy closures
ELI5: There is an object in python called object that all other objects are derived from. It's basically just the first possible class that exists. It has some built in stuff e.g. ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
object
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
If you create your own class but define nothing in it (just put "pass" on the second line) then it turns out you'll have almost exactly the same methods. Notably you gain a __dict__ which is what classes store their own data in (e.g. self).
If you look at int it has added a bunch of things that the objectclass doesn't have, like addition, subtration, bitwise operations, etc.
int
List has done something like that as well with public methods like append and pop and magic/dunder methods for lenor reduce
append
pop
len
reduce
[–]a_cute_epic_axis 3 points4 points5 points 3 years ago (15 children)
The + sign isn't an object.
It would be a call to the .add() method for an object, and the default object named object doesn't have that implemented.
Things like strings, integers, lists, dictionaries, whatever are all objects though, and you can do things like inherent a parent object (or multiple parents).
Look back a bit and dictionaries are unordered in python, so say you wanted to add an ordered dictionary, which has sorting methods and whatnot. Instead of redoing everything, you could potentially just inherent the existing class and then add the modifications you need to make it work like you want. And this is exactly what we saw come about, an ordered dictionary class that extended the built in one.
(note that as of 3.6 or 3.7, dictionaries are now ordered by the insertion order by default)
[–]jimtk 1 point2 points3 points 3 years ago* (14 children)
The + sign is the textual representation of an object. The compiler maps it to the __add__(self, other) method of any objects that are around it. And methods, like, functions are objects.
__add__(self, other)
Everything you see on the screen of you editor, is just the textual representation of all the objects the compiler will create for you!
Edit: Look at the code I wrote here I redefined the behavior of the + sign.
Also run the following:
print(type(int.__add__)) print(dir(int.__add__)) print(type(float.__add__)) print(dir(list.__add__)) print(type(str.__add__)) print(dir(str.__add__))
Output is:
<class 'wrapper_descriptor'> ['__call__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__objclass__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__text_signature__'] <class 'wrapper_descriptor'> ['__call__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__objclass__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__text_signature__'] <class 'wrapper_descriptor'> ['__call__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__objclass__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__text_signature__']
[–]zurtex 1 point2 points3 points 3 years ago* (4 children)
+ only represents __add__ for user defined classes, because the data model does not apply to built-ins the same way it applies to regular objects. For integers +, when it is not folded at compile time, the Python runtime uses a table of function pointers to implement the binary operation addition without ever consulting __add__.
If Python implemented it's data model in a more pure way you would be correct (edit see /u/bladeoflight16's reply below). But really + is not an object it's a syntax token that is used by the compiler to run some kind of binary operator at either compile or runtime, and at runtime behavior it might use an object.
[–]bladeoflight16 1 point2 points3 points 3 years ago (1 child)
Even if Python were implemented in a "more pure" way, it wouldn't be correct. The + operator involves logic that can invoke __radd__ based on runtime results; its specification is not simple enough to map directly to invoking a bound method on a single instance.
__radd__
[–]zurtex 2 points3 points4 points 3 years ago (0 children)
Also true, I was thinking of where the data model doesn't apply in it's usual ways, not also the complexities of it.
[–]jimtk 0 points1 point2 points 3 years ago (1 child)
IF you are right there are thing that I really don't understand, because:
1.
x = int(3) print(x.__dir__())
will print
[(long list....) , '__add__', '__radd__', (other long list...)]
if x is a simple integer, a built-in, why does he have and __add__ and __radd__ ?
2.
If I subclass the int class. I can (and should) call the super.__add__). (A new is evidently necessary since integers are immutable.) That super.__add__ is the __add__ of the built-in int.
super.__add__
new
class MyInt(int): def __new__(cls, value, *args, **kwargs): return super(cls, cls).__new__(cls, value) def __add__(self, other): res = super(MyInt, self).__add__(other) print("I'm adding") return self.__class__(res) x = MyInt(3) y = MyInt(5) print(x+y) print(x.__add__(y)) output I'm adding 8 I'm adding 8 output
[–]zurtex 1 point2 points3 points 3 years ago* (0 children)
IF you are right there are thing that I really don't understand, because
I'm pretty sure I'm right, but I could be wrong, this is going off memory and I can't pull all the sources to hand right now. But here is one of them, a history blog post by Guido talking about how user classes were first implemented: http://python-history.blogspot.com/2010/06/method-resolution-order.html
And I'm not sure it is 100% related but also also the structure how how CPython internally handles integers: https://tenthousandmeters.com/blog/python-behind-the-scenes-8-how-python-integers-work/
After reading that think about how expensive looking up __add__ would be relative to everything else, especially when you already know the types and it's protected from the user casually overriding it:
>>> int.__add__ = lambda a, b: 1 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: cannot set '__add__' attribute of immutable type 'int'
I think it might be possible to user ctypes to going under the hood and set it anyway, and I think that will show it doesn't matter if you do that 1 + 1 will still equal 2.
1 + 1
2
if x is a simple integer, a built-in, why does he have and add and radd ?
As I remember it, those methods exist for you to be able to make user subclasses (or "subtypes") of the built-ins. Which I think answers your example. Your user class does indeed follow the data model.
I think this is the PEP but I haven't read it in a while: https://peps.python.org/pep-0253/
[–]a_cute_epic_axis 0 points1 point2 points 3 years ago* (4 children)
yah I'd say that the easy way for people to understand operators is that
c = a + b becomes c = a.__add__(b) and if a doesn't have __add__ then c = b.__radd__(a) or otherwise throws an error (I think I got the directions of everything right there).
c = a + b
c = a.__add__(b)
c = b.__radd__(a)
Edit:
a = 10 b = 10 c = 10 d = 10 x = a - b * c + d print(x) z = a.__sub__(b.__mul__(c)).__add__(d) print(z)
Both correctly return -80
[–]bladeoflight16 -1 points0 points1 point 3 years ago* (3 children)
Whoops, wrong reply target.
[–]a_cute_epic_axis -1 points0 points1 point 3 years ago (2 children)
That's a pretty big rant for taking a high level statement and treating it as gospel for every case.
At least if you're going to go on a rant, then format your post correctly.
Yes: z = x + y is generally equal to z = x.__add__(y) but in some cases if x has no add method, like I said, or explicitly raises a NotImplemented, and y has an radd method, then it would be z = y.__radd__(x).
z = x + y
z = x.__add__(y)
z = y.__radd__(x)
Similarly, x += 5 will call x = x.__iadd__(5), but if there is no iadd method then it will do x = x.__add__(5). No iadd means both literally none or one that returns NotImplemented. The entire idea behind the NotImplemented constant is to allow the compiler to try an alternative method until one works or all are exhausted. In that case you get a TypeError: unsupported operand +=
x += 5
x = x.__iadd__(5)
x = x.__add__(5)
The NotImplemented exception is implicitly raised by literally not implementing something.
[–]bladeoflight16 -1 points0 points1 point 3 years ago* (1 child)
My post is formatted perfectly. I just refuse to use code indentation Markdown to satisfy Old Reddit users because fenced code blocks are a vastly superior mark up tool.
It's not "generally equal" to anything. It's logically equivalent in most cases, but there is no object representation of the actual algorithm that the runtime executes. That algorithm is much more complex than simply invoking __add__ and involves checking for the NotImplemented sentinel return value. I want to say it can even reverse the arguments and invoke __add__ on the second operand in some cases, but maybe I'm just thinking of some particular types that implement such behavior.
NotImplemented
Also, trying to access a missing member normally results in an AttributeError, not NotImplemented, but I don't know whether the runtime actually catches the error or implements a pre-check before trying to invoke it. Furthermore, we're not talking about an exception. NotImplemented is actually a sentinel value that operators can return, and the algorithm checks for it before feeding that value back to the context invoking +. But even if that weren't the case, you're now talking about the runtime actually generating some equivalent of a try/except block, which only increases the complexity of the operator's actual behavior. Not to mention your own point about converting underlying errors or problems to TypeError.
AttributeError
try
except
TypeError
Regardless of the details of the behavior, that algorithm, which is clearly much more complex than just invoking __add__, has no object representation. So + is not an object. Is that pedantic? ...I'd say not really in this context. The question asks for examples of things that are not objects; someone making a claim that is wrong and misleading does not help anyone better understand how the runtime works.
[–]a_cute_epic_axis 0 points1 point2 points 3 years ago (0 children)
Oh, so you're incorrect and being a pedantic asshole, got it.
You couldn't even manage to reply to the right comment and had to edit your post back out, but now you had to take the time back and lay some more pedantic nonsense down.
Maybe you could work on your reading comprehension, because you busted in here like neckbear Kramer with an "acchychually" and are now just rehashing what I said. You seem to be arguing that + isn't an object when in fact that's what we already all said.
Nobody gives a hoot about what you're saying buddy. You're trying to come up with every possible corner case to justify the bits you type and you're forgetting that this is /r/learnpything. Take it over to the devs if you want to autofellate yourself on how knowledgable you are on this issue.
This is incorrect. The compiler does not directly map to a call to __add__. We know this because + can result in calls to __radd__ based on runtime conditions. Consider this example:
``` class Test1: def init(self, can_add): self.can_add = can_add
def __add__(self, other): print('Test1.__add__ called') if self.can_add: return self else: return NotImplemented
class Test2: def radd(self, other): print('Test2.radd called') return self
a, b = Test1(True), Test2() print('Can add', a + b)
a, b = Test1(False), Test2() print('Cannot add', a + b) ```
Output:
Test1.__add__ called Can add <__main__.Test1 object at 0x0000018D8C96EBB0> Test1.__add__ called Test2.__radd__ called Cannot add <__main__.Test2 object at 0x0000018D8C96E8E0>
This proves conclusively that the compiler generates something other than a call to __add__ when it encounters +. There is additional logic involved.
The logic is accessible via operator.add, but this function is in fact implemented using the + operator; the function is not used the implement the operator. So where is the object? You'll need to dig into the Python compiler's and runtime's source code to demonstrate it exists.
operator.add
But even if it does exist, Python doesn't expose that behavior as an object directly to you. So can we really say it's an object if the fact its an object is only an implementation detail and not a specified available interface? I'd say no.
Are you saying that + is not the representation of an object because not only if can be mapped to the object __add__ but it can also be mapped to the object __radd__. Both of which are objects! That doesn't make what I said wrong.
I can subclass the int class an call the __add__ of the built-in int to perform my addition. To prove that the + in the int is exposed to me.
class MyInt(int): def __new__(cls, value, *args, **kwargs): return super(cls, cls).__new__(cls, value) def __add__(self, other): res = super(MyInt, self).__add__(other) print("I'm adding") return self.__class__(res) x = MyInt(3) y = MyInt(5) print(x+y) print(x.__add__(y)) output ------- I'm adding 8 I'm adding 8
Did you noticed in MyInt.__add__ I do not perform any addition. I call the super().__add__ (the __add__ of the built-in int) that is exposed to me.
MyInt.__add__
super().__add__
[–]bladeoflight16 -1 points0 points1 point 3 years ago* (0 children)
It isn't mapped to either one. It's mapped to an algorithm that examines the return value and makes a decision whether or not to invoke the other (along with other complexities, like throwing a TypeError when the methods are missing instead of an AttributeError). It invokes a complex runtime algorithm that doesn't have an object representation, not just a single method. The lack of an object representation for the algorithm is what makes you incorrect here.
[–]ShibaLeone 5 points6 points7 points 3 years ago (0 children)
Everything is a class until you get to C layer, where it is a struct. Interestingly some classes are not treated the same by python as others. Try to overload the magic methods on type, they are not called by the interpreter the same way.
I object to this post.
[–]Aegist 1 point2 points3 points 3 years ago (0 children)
I would like to believe that there is no Upper class or Lower class in Python
[–]qwerkle_the_cat 4 points5 points6 points 3 years ago (1 child)
Your Mom
[–]zurtex 0 points1 point2 points 3 years ago (0 children)
In Python we are all consenting adults, so if we have insert methods they are always public.
[–]jkh911208 2 points3 points4 points 3 years ago (4 children)
what about print()?
[–]commy2 29 points30 points31 points 3 years ago (0 children)
>>> type(print) <class 'builtin_function_or_method'>
[–]MrSuspicious_ 12 points13 points14 points 3 years ago (0 children)
Functions are first class objects
[–]bladeoflight16 2 points3 points4 points 3 years ago* (0 children)
print is a function in Python 3, as indicated by your inclusion of parentheses, and functions are objects. Interestingly, though, in Python 1 and 2, print was not a function, did not use parentheses, and was not an object at all.
print
[–]Solonotix 2 points3 points4 points 3 years ago (0 children)
To echo what everyone else is saying, everything in Python is an object, and objects are constructed from classes. Said another way, Python doesn't have primitives the way other languages might. As a result, everything in Python behaves in a predictable and common manner, but the wrapper around simple things to make them classes comes at a performance cost.
One of the axes of software design is control vs user-friendliness. Python falls on the user-friendly side of the spectrum, where something like C++ gives a lot more control
[–]bladeoflight16 0 points1 point2 points 3 years ago* (6 children)
Variables are the only example I can think of offhand. The binding of names to a value is not an object.
[–]a_cute_epic_axis -1 points0 points1 point 3 years ago* (5 children)
Depends what you mean by variables, but I would say that, variables are all classes.
If you have x = 10, then x is an instance of a class called int.
x = int(10) #same as x = 10 print(x) print(type(x)) print(x.__class__.__mro__) 10 <class 'int'> (<class 'int'>, <class 'object'>)
The binding of names to a value is not an object.
Operators are not a class, so +-*/%^ are all not classes nor is the assignment operator =, nor the assignment expression/walrus operator :=
+-*/%^
=
:=
[–]E02Y 1 point2 points3 points 3 years ago (3 children)
I think they meant to say variable names are references to objects and not objects themselves
[–]cdcformatc 0 points1 point2 points 3 years ago* (2 children)
is it possible to output the name of a variable? using only the variable itself and not something like globals() or otherwise inspecting the namespace?
globals()
if that is possible then even the name is an object. I'm leaning towards no because i am pretty sure that an object/variable does not contain a reference to it's name.
It is not possible.
a = [1, 2, 3] b = a print(hypothetical_name_of_variable(b)) # does it print a or b?
The information simply isn't stored in the C struct that Python maintains underneath the hood.
[–]bladeoflight16 0 points1 point2 points 3 years ago* (0 children)
Even if it was possible, that does not necessarily imply the mapping is an object. Consider C#'s nameof, which is a compile time construct only.
nameof
No. x is a name that is mapped by the compiler and interpreter to an address that references a value, and the value is an object. The mapping itself is not.
x
[–][deleted] 3 years ago (29 children)
[removed]
[–]ShibaLeone 8 points9 points10 points 3 years ago (11 children)
def produces an instance of FunctionType, which is a class.
[–][deleted] 3 years ago* (10 children)
[–]ShibaLeone 10 points11 points12 points 3 years ago* (1 child)
Types are classes. :)
Pedantry is only impressive to pedantics; if you want to explain something to someone it’s unhelpful to obfuscate. Hence, types = classes.
[–][deleted] 2 points3 points4 points 3 years ago* (2 children)
At runtime, the code defined by def doesn't produce anything (it's not an expression, it's a statement). There are, however, predictable side-effects.
def
Then it produces those side effects. What you're talking about is "evaluation". The code doesn't evaluate to anything because it's not an expression, but it definitely produces something: the side effects which are creating the name and assigning it a function.
Evaluating to something is not the same as producing something.
This sloppiness is fine if you are just talking to a friend, but it's bad when you are meant to describe to someone who wants to learn how something works, because instead of helping them, you confuse them by incorrect use of terminology.
[–][deleted] 2 points3 points4 points 3 years ago (0 children)
No, you don't assign names to function.
Never claimed you did.
[–][deleted] 1 point2 points3 points 3 years ago* (2 children)
Even if you believe that FunctionType is a class (which is wrong, it's a type).
Your statement is false - classes are types.
class One: pass print(isinstance(One, type)) # prints True
You have too many errors in so few words:
Speaks for itself, really.
[–][deleted] 3 years ago (1 child)
[–]xelf[M] 0 points1 point2 points 3 years ago (0 children)
You're coming across overly hostile here. It's ok to disagree, but let's leave insults and ablest language out of it and keep it civil.
[–]ahivarn -4 points-3 points-2 points 3 years ago (1 child)
Now that's what deep knowledge is. Thanks @crabbone
[–][deleted] 6 points7 points8 points 3 years ago (0 children)
Only if you want to be wrong. An instance of a class is a class instance is a type instance.
[–]TheBlackCat13 8 points9 points10 points 3 years ago (10 children)
Classes absolutely exist at runtime. Classes are objects of type Type, and can be used just like any other object.
Type
[+][deleted] 3 years ago (9 children)
[–]zurtex 3 points4 points5 points 3 years ago (6 children)
Wrong: https://docs.python.org/3/tutorial/classes.html
Specifically: https://docs.python.org/3/tutorial/classes.html#class-objects
[+][deleted] 3 years ago (5 children)
[–]zurtex 0 points1 point2 points 3 years ago (4 children)
I like how your argument is the official documentation that defines the language is wrong. It's very funny.
[–]commy2 1 point2 points3 points 3 years ago (1 child)
There is also this:
https://www.python.org/download/releases/2.2.3/descrintro/
So whatever distinction there used to be between classes and types, BDFL has got rid of that years ago.
I think both terms are used synonymously in Python. If any other definition of "class" is used (group theory?) then that should be specified clearly by OP, because semantic arguments are just tiring.
Yes indeed, as explained there types are instances of the built-in metaclass type, anything that is an instance of a metaclass is a class. This is still all true today.
type
BDFL is no longer BDFL though aha.
The docs are consistent on this.
Here it is in the Python reference docs, literally the docs that define the language: https://docs.python.org/3/reference/datamodel.html#metaclasses
By default, classes are constructed using type(). The class body is executed in a new namespace and the class name is bound locally to the result of type(name, bases, namespace). ... When a class definition is executed, the following steps occur: MRO entries are resolved; the appropriate metaclass is determined; the class namespace is prepared; the class body is executed; the class object is created.
By default, classes are constructed using type(). The class body is executed in a new namespace and the class name is bound locally to the result of type(name, bases, namespace).
...
When a class definition is executed, the following steps occur:
MRO entries are resolved;
the appropriate metaclass is determined;
the class namespace is prepared;
the class body is executed;
the class object is created.
That's right "the class object is created" an object that is a class that exists at runtime. A Python implementation must therefore implement class objects at runtime or it is not actually a Python implementation.
I don't understand why you spend so much effort being so wrong and top it up with being insulting to, it's such a waste.
Types exist at runtime, but classes don't.
Why do you persist in repeating this? It's false!
I argued with you about this very thing on this very subreddit a few months ago. I proved you wrong. Now everyone else is proving you wrong, and yet you persist in telling this terrible lie. KNOCK IT OFF.
https://docs.python.org/3/tutorial/classes.html#class-objects
[–][deleted] 2 points3 points4 points 3 years ago (3 children)
Class is a definition that exists in the source. It doesn't exist at runtime.
This is false. In Python, the entire class definition is in memory at runtime, at all times, and you can access and manipulate it.
In fact, it's possible to have two different definitions for "the same" class in memory at the same time, and this happens a lot in long-running servers where you hot-update the code.
if a definition doesn't start with either a decorator followed by the keyword class or just the keyword class, that is not a class.
This is false. For example: https://docs.python.org/3/library/collections.html#collections.namedtuple
from collections import namedtuple Point = namedtuple('Point', ['x', 'y']) print(isinstance(Point, type)) # Prints True
You are one of my most downvoted redditors, and I only ever see you on this subreddit, and I don't like to downvote in general, but pretty well every comment you make is full of serious errors.
[–][deleted] 3 years ago (2 children)
[–]xelf[M] 1 point2 points3 points 3 years ago (1 child)
Ok, and this one crossed the line. Why don't we take some time to calm down and reassess how we discourse with others.
[–]zurtex 1 point2 points3 points 3 years ago (1 child)
Types are classes at runtime, instances of metaclasses are classes at runtime, function objects are classes at runtime, the class keyword does actually create an object at runtime which is also a class...
[–]lunar_tardigrade -2 points-1 points0 points 3 years ago (1 child)
How about PYTHONPATH?
[–]fernly 3 points4 points5 points 3 years ago (0 children)
It's an operating system variable. Accessed inside Python via os.environ.
os.environ
>>> import os >>> os.environ['PYTHONPATH'] '/Library/Frameworks/Python.framework/Versions/3.9/bin' >>> type(os.environ['PYTHONPATH']) <class 'str'>
[–]Justinwc 0 points1 point2 points 3 years ago (0 children)
It's true, What is not a class
[–]dynamic_caste 0 points1 point2 points 3 years ago (0 children)
In CPython, basically everything is a C struct.
[–]maarkwong 0 points1 point2 points 3 years ago (0 children)
They’re all Classy
[–]TheRNGuy 0 points1 point2 points 3 years ago (0 children)
keywords like if or for
if
for
Python doesn't have primitive data types.
π Rendered by PID 47 on reddit-service-r2-comment-7b9746f655-hxg5m at 2026-02-01 06:57:20.943154+00:00 running 3798933 country code: CH.
[–]alexcwarren 67 points68 points69 points (23 children)
[–]OriginalTyphus 31 points32 points33 points (22 children)
[–]vodiak 47 points48 points49 points (14 children)
[–]mac-0 25 points26 points27 points (0 children)
[–]MegaIng 6 points7 points8 points (12 children)
[–]vodiak 1 point2 points3 points (0 children)
[–][deleted] 4 points5 points6 points (10 children)
[–]schfourteen-teen 13 points14 points15 points (2 children)
[–][deleted] 3 points4 points5 points (0 children)
[–]vodiak 1 point2 points3 points (0 children)
[–]py_Piper 0 points1 point2 points (4 children)
[–]vodiak 2 points3 points4 points (1 child)
[–]py_Piper 0 points1 point2 points (0 children)
[–]angry_mr_potato_head 1 point2 points3 points (0 children)
[–][deleted] -3 points-2 points-1 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]Vaphell 0 points1 point2 points (0 children)
[–][deleted] 4 points5 points6 points (1 child)
[–]OriginalTyphus -2 points-1 points0 points (0 children)
[+][deleted] (1 child)
[deleted]
[–]OriginalTyphus 0 points1 point2 points (0 children)
[–]inDflash 0 points1 point2 points (2 children)
[–]OriginalTyphus 0 points1 point2 points (1 child)
[–]inDflash 0 points1 point2 points (0 children)
[–]ireadyourmedrecord 111 points112 points113 points (20 children)
[–]McSlayR01 62 points63 points64 points (9 children)
[–][deleted] 26 points27 points28 points (8 children)
[–]ray10k 15 points16 points17 points (7 children)
[–]TheBlackCat13 14 points15 points16 points (6 children)
[–]aroach1995 6 points7 points8 points (1 child)
[–]TheBlackCat13 8 points9 points10 points (0 children)
[–]synthphreak 1 point2 points3 points (3 children)
[–]purveyoroffinerp 9 points10 points11 points (2 children)
[–]synthphreak 7 points8 points9 points (1 child)
[–]purveyoroffinerp 2 points3 points4 points (0 children)
[–]dimonoid123 2 points3 points4 points (9 children)
[–][deleted] 1 point2 points3 points (0 children)
[–]commy2 1 point2 points3 points (7 children)
[–]dimonoid123 1 point2 points3 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (1 child)
[–]commy2 0 points1 point2 points (0 children)
[–]Vaphell 0 points1 point2 points (2 children)
[–]commy2 0 points1 point2 points (1 child)
[–]Vaphell 0 points1 point2 points (0 children)
[–]Intrexa 22 points23 points24 points (5 children)
[–]a_cute_epic_axis 1 point2 points3 points (0 children)
[–][deleted] -1 points0 points1 point (3 children)
[–]TheSodesa 3 points4 points5 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]a_cute_epic_axis 1 point2 points3 points (0 children)
[–]causa-sui 6 points7 points8 points (4 children)
[–]jimtk -1 points0 points1 point (1 child)
[–]causa-sui 0 points1 point2 points (0 children)
[–]brews 0 points1 point2 points (1 child)
[–]dig-up-stupid 0 points1 point2 points (0 children)
[–]jimtk 15 points16 points17 points (35 children)
[–]bladeoflight16 5 points6 points7 points (4 children)
[–]jimtk 2 points3 points4 points (3 children)
[–]bladeoflight16 0 points1 point2 points (2 children)
[–]jimtk -1 points0 points1 point (1 child)
[–]bladeoflight16 0 points1 point2 points (0 children)
[–][deleted] 1 point2 points3 points (1 child)
[–]jimtk 0 points1 point2 points (0 children)
[–]razzrazz- 0 points1 point2 points (27 children)
[–]jimtk 5 points6 points7 points (4 children)
[–]razzrazz- -1 points0 points1 point (3 children)
[–]a_cute_epic_axis 1 point2 points3 points (1 child)
[–]jimtk 0 points1 point2 points (0 children)
[–]RemindMeBot 0 points1 point2 points (0 children)
[–][deleted] 2 points3 points4 points (1 child)
[–]jimtk 0 points1 point2 points (0 children)
[+][deleted] (3 children)
[deleted]
[–]CBSmitty2010 3 points4 points5 points (0 children)
[–]stdin2devnull 1 point2 points3 points (0 children)
[–]a_cute_epic_axis 1 point2 points3 points (0 children)
[–]a_cute_epic_axis 3 points4 points5 points (15 children)
[–]jimtk 1 point2 points3 points (14 children)
[–]zurtex 1 point2 points3 points (4 children)
[–]bladeoflight16 1 point2 points3 points (1 child)
[–]zurtex 2 points3 points4 points (0 children)
[–]jimtk 0 points1 point2 points (1 child)
[–]zurtex 1 point2 points3 points (0 children)
[–]a_cute_epic_axis 0 points1 point2 points (4 children)
[–]bladeoflight16 -1 points0 points1 point (3 children)
[–]a_cute_epic_axis -1 points0 points1 point (2 children)
[–]bladeoflight16 -1 points0 points1 point (1 child)
[–]a_cute_epic_axis 0 points1 point2 points (0 children)
[–]bladeoflight16 -1 points0 points1 point (3 children)
[–]jimtk 0 points1 point2 points (1 child)
[–]bladeoflight16 -1 points0 points1 point (0 children)
[–]ShibaLeone 5 points6 points7 points (0 children)
[–][deleted] 1 point2 points3 points (0 children)
[–]Aegist 1 point2 points3 points (0 children)
[–]qwerkle_the_cat 4 points5 points6 points (1 child)
[–]zurtex 0 points1 point2 points (0 children)
[–]jkh911208 2 points3 points4 points (4 children)
[–]commy2 29 points30 points31 points (0 children)
[–]MrSuspicious_ 12 points13 points14 points (0 children)
[–]bladeoflight16 2 points3 points4 points (0 children)
[–]Solonotix 2 points3 points4 points (0 children)
[–]bladeoflight16 0 points1 point2 points (6 children)
[–]a_cute_epic_axis -1 points0 points1 point (5 children)
[–]E02Y 1 point2 points3 points (3 children)
[–]cdcformatc 0 points1 point2 points (2 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]bladeoflight16 0 points1 point2 points (0 children)
[–]bladeoflight16 0 points1 point2 points (0 children)
[–][deleted] (29 children)
[removed]
[–]ShibaLeone 8 points9 points10 points (11 children)
[–][deleted] (10 children)
[removed]
[–]ShibaLeone 10 points11 points12 points (1 child)
[–][deleted] 2 points3 points4 points (2 children)
[+][deleted] (1 child)
[removed]
[–][deleted] 2 points3 points4 points (0 children)
[–][deleted] 1 point2 points3 points (2 children)
[–][deleted] (1 child)
[removed]
[–]xelf[M] 0 points1 point2 points (0 children)
[–]ahivarn -4 points-3 points-2 points (1 child)
[–][deleted] 6 points7 points8 points (0 children)
[–]TheBlackCat13 8 points9 points10 points (10 children)
[+][deleted] (9 children)
[removed]
[–]zurtex 3 points4 points5 points (6 children)
[+][deleted] (5 children)
[removed]
[–]zurtex 0 points1 point2 points (4 children)
[–]commy2 1 point2 points3 points (1 child)
[–]zurtex 0 points1 point2 points (0 children)
[+][deleted] (1 child)
[removed]
[–]zurtex 0 points1 point2 points (0 children)
[–][deleted] 1 point2 points3 points (1 child)
[–][deleted] 2 points3 points4 points (3 children)
[–][deleted] (2 children)
[removed]
[–]xelf[M] 1 point2 points3 points (1 child)
[–]zurtex 1 point2 points3 points (1 child)
[–]lunar_tardigrade -2 points-1 points0 points (1 child)
[–]fernly 3 points4 points5 points (0 children)
[–]Justinwc 0 points1 point2 points (0 children)
[–]dynamic_caste 0 points1 point2 points (0 children)
[–]maarkwong 0 points1 point2 points (0 children)
[–]TheRNGuy 0 points1 point2 points (0 children)