type(obj) vs. obj.__class__ in Python, and changing an object's class.

  Рет қаралды 22,485

mCoding

mCoding

Күн бұрын

What's the difference?
Python has two way to access the type of an object. There's type(obj) and obj.__class__. What's the difference? In this video we see how they are mostly the same (and you probably shouldn't worry about it) but there is a difference in that it's possible for a class to lie about what type it is by intercepting accesses to _class__. The builtin type on the other hand will always give you the real type of the object. Although, if a class tries to lie about it's type, maybe it has a good reason for it, which means you might prefer using __class_ for this reason. It's also possible to modify an objects _class_ at runtime after the object has been created, which will truly change the type so that type(obj) and obj.__class__ both report the new type. There are some restrictions (and use cases are questionable!) but it's good to know in case you ever feel like something funny is going on.
― mCoding with James Murphy (mcoding.io)
Source code: github.com/mCodingLLC/VideosS...
docs.python.org/3/reference/d...
SUPPORT ME ⭐
---------------------------------------------------
Sign up on Patreon to get your donor role and early access to videos!
/ mcoding
Feeling generous but don't have a Patreon? Donate via PayPal! (No sign up needed.)
www.paypal.com/donate/?hosted...
Want to donate crypto? Check out the rest of my supported donations on my website!
mcoding.io/donate
Top patrons and donors: Jameson, Laura M, Dragos C, Vahnekie, Neel R, Matt R, Johan A, Casey G, Mark M, Mutual Information, Pi
BE ACTIVE IN MY COMMUNITY 😄
---------------------------------------------------
Discord: / discord
Github: github.com/mCodingLLC/
Reddit: / mcoding
Facebook: / james.mcoding
CHAPTERS
---------------------------------------------------
0:00 Intro
0:34 How to use type(obj)
1:43 What about obj.__class__?
3:08 Lie about your _class_
3:56 Changing _class_ at runtime
6:44 Example: custom module type
7:36 Example: Reading pre-initialized object
9:34 Thanks

Пікірлер: 123
@Serpent10i
@Serpent10i 11 ай бұрын
Wow that is seriously cursed
@danwellington3571
@danwellington3571 11 ай бұрын
#type Directly accessing dunder attributes/methods almost always looks janky
@AntonioZL
@AntonioZL 11 ай бұрын
it's not janky, it's **pythonic** 🤩
@lawrencedoliveiro9104
@lawrencedoliveiro9104 11 ай бұрын
Remember that somebody has to.
@sinom
@sinom 11 ай бұрын
​@@AntonioZL using stuff like type is pythonic. Using dunders directly goes against all the abstraction python is known for
@FastKnight401
@FastKnight401 11 ай бұрын
@@sinom people who use the ___class___ variable in a class method (not the attribute, the variable) or the ___name___ attribute of classes:
@AntonioZL
@AntonioZL 11 ай бұрын
I tend to use #class for user defined classes or more abstract classes, and #type for base types, like ints or strs.
@Phaust94
@Phaust94 11 ай бұрын
I used to be a #class person before your video, but now I'm totally #type. Thanks as always for deep dives and interesting facts about Python. Love your vids, keep it up!
@Kenionatus
@Kenionatus 11 ай бұрын
For me it's funnily the inverse. If an object lies about its class it probably has a *really* good reason to do so.
@Scymet
@Scymet 11 ай бұрын
#class thanks for the demonstration, that's good to know
@SyberiaK
@SyberiaK 11 ай бұрын
I'm feeling like #class is more convenient while working with a class and #type is more convenient while working with plain types (e.g. int, str, float, bytes)
@MilChamp1
@MilChamp1 11 ай бұрын
5:16 i nearly spat out my tea, thanks James
@mathieuflouret7177
@mathieuflouret7177 11 ай бұрын
#class, and I actually use the runtime class change in one of my projects. Yes, it has an actual use in my case. But where I do it, the classes basically don't have any extra initialization to be done, so... Bad code quality, but it's the only way it works. At least it works. EDIT: My bad, I'm modifying instance.___bases___ rather than instance.___class___ ! Sorry for the confusion !
@umion9529
@umion9529 9 ай бұрын
If you have ur project on github, would u be able to share your proj. Im mere curious about ur particular kind of task where you're required to change _bases_ at runtime
@jemand771
@jemand771 11 ай бұрын
so when are we getting reinterpret_cast for python objects
@adamdapatsfan
@adamdapatsfan 11 ай бұрын
5:16 that was incredible, so out of left field, I love it. #type
@paper_cut9457
@paper_cut9457 11 ай бұрын
Thanks for the (as usual) precious insight! I wonder, is the behaviour of "isinstance" affected by this ?
@mCoding
@mCoding 11 ай бұрын
Fantastic question that has a weird answer! Assuming you don't use a custom isinstance check by overriding __instancecheck__, the default behavior is to check _*_BOTH_*_ the real type's MRO and the __class__'s MRO. So if you have A < object, Liar < object, and Liar lies and says its __class__ is A, then isinstance(Liar(), A) and isinstance(Liar(), Liar) will both return True! Here's a compiler explorer link to play with this example: godbolt.org/z/fE8Ke5PWa
@felixfourcolor
@felixfourcolor 10 ай бұрын
Thank you for asking what I need to know but didn't know to ask
@thagreatone402
@thagreatone402 11 ай бұрын
Im working on an admin panel builder for flask. Definitely been pushing all these techniques to the extreme.
@RichardFeynman2282
@RichardFeynman2282 11 ай бұрын
#class I never knew you could use type(self) in place of self.__class__, so it looks funny :|
@DanCojocaru2000
@DanCojocaru2000 11 ай бұрын
But when you add two things do you do x.__add__(y) or x + y? Calling dunder stuff is always sketchy.
@lawrencedoliveiro9104
@lawrencedoliveiro9104 11 ай бұрын
“+” translates to the add method call--that’s how it’s defined to work. Dunder methods are there because somebody, at some point, has to call them.
@FastKnight401
@FastKnight401 11 ай бұрын
@@DanCojocaru2000 people who use the ___class___ variable in a class method (not the attribute, the variable) or the ___name___ attribute of classes:
@julianbazanaguirre8439
@julianbazanaguirre8439 10 ай бұрын
Dude! You are carrying us to dark side of python, keep it on! I really love you channel. Yours and the one from ArjanCodes just have fantastic content.
@mCoding
@mCoding 10 ай бұрын
Thanks so much, I appreciate the encouragement!
@Cyber_Chriis
@Cyber_Chriis 11 ай бұрын
8:35 this is actually cool and useful!
@QuantumHistorian
@QuantumHistorian 11 ай бұрын
#3:40 you don't do that because you have great job security, but as a way of getting it! If nobody else can maintain your code, they can't get rid of you
@panosemp
@panosemp 11 ай бұрын
Another case where you might consider modifying an object's __class__ attribute is when you have a library providing a class A with a corresponding factory function build_A. Now, if you want to create a subclass B with a similar factory function build_B, you could modify the __class__ attribute of instances created by build_A to B to avoid duplicating the code from build_A
@fiNitEarth
@fiNitEarth 11 ай бұрын
#type
@elrandira
@elrandira 11 ай бұрын
my god, I was just thinking about this topic this morning in my bed and now I get a new video from you on this topic.. #Google_reading_minds
@fartzy
@fartzy 10 ай бұрын
"If you do this you must have incredible job security" lol I come here for the jokes!
@gustavomendez2891
@gustavomendez2891 11 ай бұрын
Changing the class off an object must violate the geneva convention. Jokes aside. Has anyone used this feature? I feel kinda curious
@mCoding
@mCoding 11 ай бұрын
I haven't seen it in production :)
@gustavomendez2891
@gustavomendez2891 11 ай бұрын
Ironically, working today I got an error from ipython that I think comes from using it
@tobylegion6913
@tobylegion6913 11 ай бұрын
Just found your channel and subbed. This is the second video I see from you, the other was 25 nooby habits. Just letting you know: while this is still perfectly audible, your older video had way better audio, and I can see this 'dull' sound leading to fatigue.
@mCoding
@mCoding 11 ай бұрын
Thanks for bringing this up! I don't hear any difference and i don't realize what im doing different. What about the current audio is not as good? Is it too quiet? Popping noises? Equalization? Background noise? Any feedback is greatly appreciated.
@brandonhicks7549
@brandonhicks7549 11 ай бұрын
I could see using the last example as a way of directly initializing an object from a correctly written JSON dictionary
@felixfourcolor
@felixfourcolor 10 ай бұрын
#type If a builtin function is avaiilable, as a matter of style, I always prefer it over a dunder attribute/method. Like, no one would write `list.__setitem__(index, value)` instead of `list[index] = value`, so why treat `__class__` differently?
@GanerRL
@GanerRL 11 ай бұрын
#type: 'type(𝕊)' is shorter than '𝕊.__class__'
@AsgerJon
@AsgerJon 11 ай бұрын
#metaclass
@MarioFanGamer659
@MarioFanGamer659 11 ай бұрын
Team #type because it is more intuitive for me that way.
@RupeshBhandari-977
@RupeshBhandari-977 11 ай бұрын
#class
@marckiezeender
@marckiezeender 7 ай бұрын
I use #type for runtime type checking, i.e. type(obj1) == type(obj2). I use #class for introspection-like scenarios, especially if I'm viewing the classname. like print(self.__class__.__name___). I would never write: if obj.__class__ == int nor would I write print(type(self).__name__)
@yaroslavdon
@yaroslavdon 11 ай бұрын
Today I've learnt yet another way to hack Python 😁 #class
@paridhaxholli
@paridhaxholli 10 ай бұрын
#type all the way
@MmKayUltra1
@MmKayUltra1 11 ай бұрын
#type so that you can use it wherever you want.
@itsmaxim01
@itsmaxim01 4 ай бұрын
pretty sure the convention is everything starting with an underscore is private/protected and shouldn’t be used.
@unperrier5998
@unperrier5998 11 ай бұрын
#class of course
@DanCojocaru2000
@DanCojocaru2000 11 ай бұрын
"of course"
@treyheaney9483
@treyheaney9483 10 ай бұрын
#type- I'm of the belief we should directly reference dunders as little as possible.
@Yazan_Majdalawi
@Yazan_Majdalawi 11 ай бұрын
#type looks more stable, I wouldn't use class except if I needed its extra functionality.
@haxwithaxe
@haxwithaxe 8 ай бұрын
#class do what you mean and go straight to the source. There is no sense in asking `type` what the the class is if the class can tell you itself.
@Tomyb15
@Tomyb15 11 ай бұрын
type(obj) ? obj.__class__? How about obj.__class__.__class__(obj) But for real, #type is the proper way
@mCoding
@mCoding 11 ай бұрын
This is some wonderful #cursed-code
@n0ame1u1
@n0ame1u1 11 ай бұрын
I don't even understand what this is even doing. What even is the class of a class, some kind of class for representing types I guess. You're like constructing a type object from the given object?
@FastKnight401
@FastKnight401 11 ай бұрын
@@n0ame1u1 the class of a class is "type". Yep, "type" isn't a function, it's a class.
@daniihh
@daniihh 11 ай бұрын
#type, it seems odd that it would be a property
@Diapolo10
@Diapolo10 11 ай бұрын
I'm a #class user myself. No particularly strong reason, I'm just used to it.
@evandrofilipe1526
@evandrofilipe1526 11 ай бұрын
#type because inheritance blows let's be honest
@lior_haddad
@lior_haddad 11 ай бұрын
#type because aside from the global method lookup it should be faster, maybe, probably not
@SkyyySi
@SkyyySi 11 ай бұрын
Besides the fact that worrying about such a thing *in Python* is a severe mindset problem (though really, all premature optimization is bad), looking up a key in a dictionary should be faster than looking up and calling a function.
@anon_y_mousse
@anon_y_mousse 11 ай бұрын
​@@SkyyySi What does the function do to generate the type info and how are dictionaries in Python implemented?
@SkyyySi
@SkyyySi 11 ай бұрын
@@anon_y_mousse Since that doesn't ultimately tell us that much, I did the thing to actually do when you want to know whether something is faster: measuring. The answer is that the dunder class version actually is slower. Doing 100 million iterations, the dunder version took about 13 seconds per run while the type() version took about 12. In other words, the difference is about 10 *nanoseconds* per run (assuming I didn't mess up the conversion _cough_). So if you worry about that in the slightest: stop using Python.
@anon_y_mousse
@anon_y_mousse 11 ай бұрын
@@SkyyySi I actually wasn't worried, just curious. I guess I'll have to open up the source for Python to sate that curiosity, but that's okay, it's written in C. I would assume that the function call does more or less the same thing, just that it queries some kind of hidden dictionary and that dictionaries are just hash tables, but I don't know for certain, yet.
@FastKnight401
@FastKnight401 11 ай бұрын
@@SkyyySi To further add to the point, even in languages like C/C++, this difference is usually insignificant.
@diamonddemon7612
@diamonddemon7612 11 ай бұрын
#class cos it just looks better and since its not calling a function it faster
@kmn1794
@kmn1794 11 ай бұрын
type is actually faster and looks better. Perhaps it looks bad among a large block of dunder attribute accesses?
@FastKnight401
@FastKnight401 11 ай бұрын
@@kmn1794 well, actually, ___class___ is faster, but it's so small, you really shouldn't base your decision around this. The speed difference is basically insignificant, even in languages like C/C++. It's definitely not worth considering in python.
@kmn1794
@kmn1794 11 ай бұрын
@@FastKnight401 You are correct. Although, I really wasn't expecting that to be the case. I was comparing the read of general class attributes rather than x.__class__ specifically. Guess its got to do with the internals of python. Impressive that the performance negligibility of this point is comparable to C/C++. Still, just knowing that the class way is 1.25 faster than the type way is tempting to use everywhere, however, I think the type way is more readable and its easy to use a regex to convert between both ways. Whenever I see dunder class I think of class mutation not getting the type.
@kmn1794
@kmn1794 24 күн бұрын
type(x) is better than x.__class__ when you want the truth.
@guddi8
@guddi8 11 ай бұрын
I like #class more, just looks better, ig
@mubrik_
@mubrik_ 9 ай бұрын
well 2:25 so #class 😂
@senyai
@senyai 11 ай бұрын
#class type(a) => 5 instructions; a.__class__ => 2 instructions class is two times faster: `timeit('type(a)', 'class A:pass a=A()')` vs `timeit('a.__class__', 'class A:pass a=A()')`
@SkyyySi
@SkyyySi 11 ай бұрын
Premature optimization...
@SkyyySi
@SkyyySi 11 ай бұрын
@@kmn1794 For the record, that's a joke, right?
@FastKnight401
@FastKnight401 11 ай бұрын
It's not 2 times faster when I check. In 100 million iterations, it averages 1.7 seconds vs. 1.2 seconds, so only a 0.5 second difference. And I doubt you're doing this 100 million times. If this small of a difference matters, then you should really be using/making a C extension or writing in a different language. And even in C/C++, it's rare to care about this small of a difference, since you're never calling this cheap of a function this many times in most cases. You're usually more focused on the bigger changes, that can cause more noticeable differences. So you really shouldn't be looking at a small difference that most people, even in fast languages, won't look at, in as slow of a language as python.
@anon_y_mousse
@anon_y_mousse 11 ай бұрын
I don't write a whole lot of Python, so I've never used either, but I would definitely rather use #type because I kind of dislike typing underscores. That's also part of why I dislike operator overloading in Python, that and the names don't always make sense, such as __truediv__ and __floordiv__. I would prefer a name like fdiv and idiv to denote which, but it's still weird to me that they use // for integer division when to me that's a comment.
@stxnw
@stxnw 9 ай бұрын
holy shit this is the most retarded comment i’ve read in a while. a shit ton of personal opinions carried from another language with zero logical reasoning.
@bee_irl
@bee_irl 11 ай бұрын
#class. _tell me your sweet little lies~_
@andreasnulein782
@andreasnulein782 11 ай бұрын
Nice updog joke
@agrahajigyasu1715
@agrahajigyasu1715 11 ай бұрын
are you the dude from silicon valley bro
@mCoding
@mCoding 11 ай бұрын
Which one 🤔
@TheHackysack
@TheHackysack 10 ай бұрын
i am a dog now
@archibald-yc5le
@archibald-yc5le 11 ай бұрын
dunder #class , I don't know it just looks more pythonic
@DanCojocaru2000
@DanCojocaru2000 11 ай бұрын
And yet the Pythonic way is to always avoid dunder stuff unless absolutely needed. str(x) instead of x.__str__, iter(x) instead of x.__iter__, next(x) instead of x.__next__, x + y instead of x.__add__(y) and so on.
@Zhaxxy
@Zhaxxy 11 ай бұрын
it looks ugly for a reason, dunder methods are rarely meant to be called directly and should only be called internally by python
@__mrmino__
@__mrmino__ 11 ай бұрын
​​@@Zhaxxy that's demonstrably untrue. Dunders are meant to denote a field being a part of a protocol. The underscores are meant to avoid naming collisions. In many cases there isn't even a nondunder way to do something. Also, stop gaslighting yourself. Whenever you are doing 'def __dunder__' in python, that is just an assignment hidden by a layer of syntactic sugar.
@Zhaxxy
@Zhaxxy 11 ай бұрын
@@__mrmino__ exactly its hidden away
@__mrmino__
@__mrmino__ 11 ай бұрын
@@Zhaxxy Syntactic sugar part tells you that the "hiding" is just for syntax. The rest is just a name. Many classes from stdlib define their own dunders which are meant to be accessed in specific circumstances, and this is by design. It's not about hiding these fields, it's about having a separate namespace for overridable fields that are used as language features.
@everytimeifall
@everytimeifall 10 ай бұрын
Please don’t try this at home! Too much of job security can get the whole business out of job
@Nominal_GDP
@Nominal_GDP 11 ай бұрын
then we say YOURE A DOG NOW
@gardnmi
@gardnmi 11 ай бұрын
I use the one copilot auto fills for me 😅
@arnontzori
@arnontzori 11 ай бұрын
Thank you for my job security
@rx97_mc
@rx97_mc 11 ай бұрын
you are a dog now 🐕
@schrummy14
@schrummy14 11 ай бұрын
#type
@knut-olaihelgesen3608
@knut-olaihelgesen3608 11 ай бұрын
#class
@Zhaxxy
@Zhaxxy 11 ай бұрын
#type
@DanCojocaru2000
@DanCojocaru2000 11 ай бұрын
#type
@murphygreen8484
@murphygreen8484 11 ай бұрын
#type
@YeloFelo
@YeloFelo 11 ай бұрын
#type
@anselmschueler
@anselmschueler 11 ай бұрын
#type
@greasedweasel8087
@greasedweasel8087 11 ай бұрын
#type
@cefarix
@cefarix 11 ай бұрын
#type
@ablobofgarbage
@ablobofgarbage 11 ай бұрын
#type
@spaghettiking653
@spaghettiking653 11 ай бұрын
#type
@AssemblyWizard
@AssemblyWizard 11 ай бұрын
#type
@DanHartwigMusic
@DanHartwigMusic 11 ай бұрын
#type
@carlossegura403
@carlossegura403 11 ай бұрын
#type
@Keithfert490
@Keithfert490 11 ай бұрын
#type
@ilyarik8888
@ilyarik8888 11 ай бұрын
#class
@30IYouTube
@30IYouTube 11 ай бұрын
#class
@tooru
@tooru 11 ай бұрын
#class
@genkidaemon
@genkidaemon 11 ай бұрын
#class
@loicgrossetete9570
@loicgrossetete9570 11 ай бұрын
#class
Metaclasses in Python
15:45
mCoding
Рет қаралды 147 М.
Python's collections.abc | InvertibleDict
14:00
mCoding
Рет қаралды 43 М.
Она Постояла За Себя! ❤️
00:25
Глеб Рандалайнен
Рет қаралды 6 МЛН
Can You Draw The PERFECT Circle?
00:57
Stokes Twins
Рет қаралды 63 МЛН
The real purpose of Python's match statement, feat. CSTs
9:59
__new__ vs __init__ in Python
10:50
mCoding
Рет қаралды 203 М.
Unlocking your CPU cores in Python (multiprocessing)
12:16
mCoding
Рет қаралды 288 М.
How mathematicians prove something completely obvious.
3:44
Bloom Filters
11:31
mCoding
Рет қаралды 52 М.
Positional-only and keyword-only arguments in Python
9:48
mCoding
Рет қаралды 83 М.
Actually, you CAN divide by zero.
3:52
mCoding
Рет қаралды 251 М.
СЛОМАЛСЯ ПК ЗА 2000$🤬
0:59
Корнеич
Рет қаралды 2,3 МЛН
3D printed Nintendo Switch Game Carousel
0:14
Bambu Lab
Рет қаралды 2,2 МЛН
Индуктивность и дроссель.
1:00
Hi Dev! – Электроника
Рет қаралды 807 М.