User Controls
What is the purpose of a Class.
-
2018-03-22 at 1:45 PM UTCIn Python. Maybe i should go back to reading my ebooks because asking this i feel like a basic bitch, but what the hell does a class do that a function can't? I see classes in libraries all the time but it seems to me that all it does is add more syntax that you don't actually need because i can just as easily import functions. Also, if you have a class why do i need to define __self__ and self.object and whatnot but if i use a `@staticmethod` decorator i don't. What's the deal with that?
Explain it to me as if i am 5. -
2018-03-26 at 7:51 AM UTCThat's kind of a big question to answer in a comprehensive way. The mechanics of classes aren't too complex, it's more that the question digs into deep and varied cultural flows that have been in force in socialized programming for almost half a century now.
The dry textbook answer of "what is a class" is that it's a specification of a certain kind of object. A class is an archetype with a fixed collection behaviors (methods/functions) and data fields. Classes can be "instantiated" into objects that have actual values in their data fields.
It's kind of unfortunate that pretty much none of that is literally true in python since classes are objects, objects can dynamically acquire or replace fields or methods, and some classes can not be instantiated. But that's kind of the way you want to think about it, an archetype for objects which hold data and define some set of methods over that data. There's plenty of deep magicks around how classes/objects work but stick to the simple case to start. Like the string class is probably something you've worked with many times before. The string class is the thing that defines string behavior, like the `.split()` method for example. `.split()` is defined once for all strings by the class, but every string instance has different data (e.g. the string "foo" has different data than the string "bar"). A class is the "blueprint" that specifies the things all string instances have in common.
To individual questions:
Originally posted by Sophie but what the hell does a class do that a function can't?
Not much really. Classes are more of an organizational tool than anything else. Consider the file class. In python you can do things like:
myFile = open('foobar.txt', 'w')
myFile.write('foo')
myFile.close()
Note that `write` and `close` are methods of your file instance. Back in the C days you'd write the same code like:
int myFile = fopen("foobar.txt", "w");
write(myFile, "foo", 3);
fclose(myFile);
Here you're calling global functions `write` and `fclose` and you have to tell them which file you're operating on as the first arg. The way this looks on the reverse side is something like:
class File(object):
def __init__(self, filename, mode):
self.file_descriptor = open(filename, mode)
def write(self, input):
write(self.file_descriptor, input)
def close(self):
fclose(self.file_descriptor)
def open(filename, mode):
return File(filename, mode)
Is this use of a File class really any different than using functions where you're continually telling the function which data (file, in this case) you're operating on? I don't think so really. There are some very, uhh, base issues here with namespace pollution. Like if I define a `fopen` method to "forum open" some kind of thing representing a forum then I'm going to have name collision while if I'm using classes I only need to ensure my class name is unique.
Now mind you we figured out how to do non-shit namespacing sometime between C and Python (and Java falls on this shit side IMO) so it's less of an issue but if you think about like the python REPL you can do `dir(myFile)` to find out all the methods you can call on myFile. There is no equivalent in C, you just have to know which functions operate on file descriptors, so there is a discoverability advantage in classes and OOP but this is a human ergonomics issue, not a technical one.
But the key idea here is that File objects hold data (like file_descriptor) internally, each file will have its own file_descriptor that it remembers through `self` but they all share their write and close methods.Also, if you have a class why do i need to define __self__ and self.object and whatnot
You as a programmer should never have to manually specify __self__ properties, if you're doing this you're probably failing to instantiate a class first. Can you give us an example of where your'e doing this?but if i use a `@staticmethod` decorator i don't. What's the deal with that?
The staticmethod decorator is kind of an oddity. It's inherited from java. In java "everything is an object" (except some things because java is an ugly hack) derived from a class. If you want a function that isn't a method in Java the only way to do it is to make a static method which can be called without instantiating an associated object. Since python lets you declare functions which are not methods of objects the only reason to use a static method is for namespacing (your <function> is now `<Class>.<function>` so you can have like `File.open()` and `Trashcan.open()` in the same file without name collisions).
Consider applying the staticmethod decorator to the file class above. The write and close methods won't know which file descriptor to operate on, so you'd have to add an additional argument to communicate to them which file you want to close or write to. -
2018-03-26 at 7:54 AM UTCI've always had trouble seeing the point with a lot of these OO principles
-
2018-03-26 at 7:55 AM UTCI feel like I may not have answered that super clearly. Feel free to ask followups or just tell me something was unclear.
-
2018-03-26 at 7:59 AM UTC
Originally posted by Lanny That's kind of a big question to answer in a comprehensive way. The mechanics of classes aren't too complex, it's more that the question digs into deep and varied cultural flows that have been in force in socialized programming for almost half a century now.
The dry textbook answer of "what is a class" is that it's a specification of a certain kind of object. A class is an archetype with a fixed collection behaviors (methods/functions) and data fields. Classes can be "instantiated" into objects that have actual values in their data fields.
It's kind of unfortunate that pretty much none of that is literally true in python since classes are objects, objects can dynamically acquire or replace fields or methods, and some classes can not be instantiated. But that's kind of the way you want to think about it, an archetype for objects which hold data and define some set of methods over that data. There's plenty of deep magicks around how classes/objects work but stick to the simple case to start. Like the string class is probably something you've worked with many times before. The string class is the thing that defines string behavior, like the `.split()` method for example. `.split()` is defined once for all strings by the class, but every string instance has different data (e.g. the string "foo" has different data than the string "bar"). A class is the "blueprint" that specifies the things all string instances have in common.
To individual questions:
Not much really. Classes are more of an organizational tool than anything else. Consider the file class. In python you can do things like:
myFile = open('foobar.txt', 'w')
myFile.write('foo')
myFile.close()
Note that `write` and `close` are methods of your file instance. Back in the C days you'd write the same code like:
int myFile = fopen("foobar.txt", "w");
write(myFile, "foo", 3);
fclose(myFile);
Here you're calling global functions `write` and `fclose` and you have to tell them which file you're operating on as the first arg. The way this looks on the reverse side is something like:
class File(object):
def __init__(self, filename, mode):
self.file_descriptor = open(filename, mode)
def write(self, input):
write(self.file_descriptor, input)
def close(self):
fclose(self.file_descriptor)
def open(filename, mode):
return File(filename, mode)
Is this use of a File class really any different than using functions where you're continually telling the function which data (file, in this case) you're operating on? I don't think so really. There are some very, uhh, base issues here with namespace pollution. Like if I define a `fopen` method to "forum open" some kind of thing representing a forum then I'm going to have name collision while if I'm using classes I only need to ensure my class name is unique.
Now mind you we figured out how to do non-shit namespacing sometime between C and Python (and Java falls on this shit side IMO) so it's less of an issue but if you think about like the python REPL you can do `dir(myFile)` to find out all the methods you can call on myFile. There is no equivalent in C, you just have to know which functions operate on file descriptors, so there is a discoverability advantage in classes and OOP but this is a human ergonomics issue, not a technical one.
But the key idea here is that File objects hold data (like file_descriptor) internally, each file will have its own file_descriptor that it remembers through `self` but they all share their write and close methods.
You as a programmer should never have to manually specify __self__ properties, if you're doing this you're probably failing to instantiate a class first. Can you give us an example of where your'e doing this?
The staticmethod decorator is kind of an oddity. It's inherited from java. In java "everything is an object" (except some things because java is an ugly hack) derived from a class. If you want a function that isn't a method in Java the only way to do it is to make a static method which can be called without instantiating an associated object. Since python lets you declare functions which are not methods of objects the only reason to use a static method is for namespacing (your <function> is now `<Class>.<function>` so you can have like `File.open()` and `Trashcan.open()` in the same file without name collisions).
Consider applying the staticmethod decorator to the file class above. The write and close methods won't know which file descriptor to operate on, so you'd have to add an additional argument to communicate to them which file you want to close or write to.
i'd love to meet the 5 year that could understand that.
i'm guessing sophie would too, but that's a different story altogether.
. -
2018-03-26 at 8:19 AM UTCI have some questions but i will get back to it later. But for now, say i have a program with a lot of components. I would like to put each component into a file which i can import so my main python file will not be polluted by a million functions that do all sorts of things. My main question for now would be, what would be the proper way of writing the "libraries" or components that i wish to import into my main python file.
Do i just put everything in a class and put a bunch of methods in the class that i call with `import MyLib; MyLib.Method(arguments)` or what? -
2018-03-26 at 8:20 AM UTC
Originally posted by aldra I've always had trouble seeing the point with a lot of these OO principles
Yeah, OO is such a sprawling thing it's hard to talk about it as a whole. The OOP heterodoxy maintains (and I agree) that smalltalk's vision of message passing between independent stateful components was a major advancement over the ideas of structured programming that preceded it. The dream was that you could declaratively say "Printer, print this document" and not be concerned about the mechanics of moving print heads or job spooling or what have you. Message passing ended up getting reduced to method calls (which are not the same thing) circa Java which is not the same thing.
While Java was off being a half-assed compromise between C and smalltalk Fowler et.al. came along and (probably with good intentions) fucked a generation of programmers with "design patterns". If you read gang of four there's some reasonable ideas in there (although there are some really shitty ones too), but it's just some dudes who were like "we did this thing to constrain our poorly designed language and had some good results" and then rabbid idiots who took it as inviolable natural law that good software couldn't be made without. The way "design patterns" ended up getting interpreted by the community was such an unmitigated, dogmatic clusterfuck that the majority of the intelectual klout that gathered behind early OOP threw their hands up after various amounts of agony and scattered into academia and esolang hell, slowly coalescing around FP in the last 5~10 years.
5 years ago it was a really awkward case of "moderates defend extremists" where criticism of applied OOP would always be met with some smarter-than-average OOP champion claiming the ills that fall out of that style of development were in fact a misapplication of principles. And they were right. But the problem was that ended up being taken as justification of the whole of the OOP dogma. It was an especially virulent plague on commercial software development since business interests fed up with projects going over-budget and past deadlines latched onto the very noun-oriented language. Line managers could now police programming methodology by invoking design patterns on faith that they were something good.
Thankfully it's a trend that's dying out with functional programming being now nascent, but while I'm wholly behind the introduction of functional concepts to industry I can't pretend that I don't see dogma around modands, referential transparency, and no-points in the future. I think the reality is that commercial software development is always going to be a hellhole, but on the up side at least these well-intentioned movements do manage to push forward PLT at some, albeit glacial, pace. Even if it churns out a constant stream of evolutionary dead ends (COBOL, Java, PHP, even to a degree Python/Ruby) at least we manage to learn something from these traditions. -
2018-03-26 at 8:31 AM UTC
Originally posted by Sophie I have some questions but i will get back to it later. But for now, say i have a program with a lot of components. I would like to put each component into a file which i can import so my main python file will not be polluted by a million functions that do all sorts of things. My main question for now would be, what would be the proper way of writing the "libraries" or components that i wish to import into my main python file.
Do i just put everything in a class and put a bunch of methods in the class that i call with `import MyLib; MyLib.Method(arguments)` or what?
If you're writing code works reasonably as a collection of functions, then by all means, use functions instead of classes. In Python (and this isn't true of every language) it's perfectly acceptable to make a library that has multiple top level functions.
You'll want to create a class when you have some kind of data you want to model. So like in ISS we have a `Post` class and we instantiate a Post class for each post in the database. Every post can be moved beween threads so there's a `.move_to_thread()` method defined for all of them. If you have data like this, where there are many instances of the same basic type of thing, then you might want to make a class for that. If you just want to split up your logic it's perfectly fine to just keep top level functions split up across files (in ISS the `utils` file or `iss_bbcode` are good examples of this, just a hodge podge of functions and some classes that are related to each other). -
2018-03-26 at 1:52 PM UTC
Originally posted by Lanny If you're writing code works reasonably as a collection of functions, then by all means, use functions instead of classes. In Python (and this isn't true of every language) it's perfectly acceptable to make a library that has multiple top level functions.
You'll want to create a class when you have some kind of data you want to model. So like in ISS we have a `Post` class and we instantiate a Post class for each post in the database. Every post can be moved beween threads so there's a `.move_to_thread()` method defined for all of them. If you have data like this, where there are many instances of the same basic type of thing, then you might want to make a class for that. If you just want to split up your logic it's perfectly fine to just keep top level functions split up across files (in ISS the `utils` file or `iss_bbcode` are good examples of this, just a hodge podge of functions and some classes that are related to each other).
Thanks man, that's all i need for the moment. -
2018-03-26 at 7:12 PM UTCHaha! Amateurs!
-
2018-03-27 at 11:30 PM UTCIts the arch-type like Lanny said. You can use the class to create multiple objects. A function is just part of the class.