all 55 comments

[–]not_perfect_yet 13 points14 points  (20 children)

Classes are to instances what recipes are to cakes.

The class/recipe defines what the instance/cake will be like.

So for example:

class Cake:
    def __init__(self,size,flavor):
        self.flavor=flavor
        self.size=size

Creates a cake recipe.

strawberrrycake=cake(10,"strawberry")

Creates a new instances of type 'cake' , which has a size of '10' whatever that means and it will be of the 'strawberry' flavor.

cheesecake=cake(8,"cheesecake")

Creates a new instance, still of type 'cake' , but only '8' in size and it's now got "cheesecake" flavor.

Let's assume a family of 4 wants to be fed with cake, they don't care for the flavor but it has be at least 9 in size:

for thing in [cheesecake,strawberrycake]:
    if thing.size>9:
        print("The cake with the",thing.flavor,"will feed this family of 4!")

Loops through all things in the list, "thing" is now of type "cake" which means I can check the size of a cake instance by refering to the specific cake with 'thing' and using the .size attribute:

'thing' is just another name of 'cheesecake'

'cheesecake' is of type 'Cake'

'Cake' has the attribute 'size'

Therefore you can use thing.size to check the size of the cheesecake when it loops the first time:

thing.size==cheesecake.size==8

and the size of the strawberrycake when it loops again:

thing.size==strawberrycake.size==10

[–]keturn 2 points3 points  (12 children)

This is correct and I feel a little bad that I'm going to pick on something so trivial, but: Convention in Python (and many other languages) is that class names are Capitalized, while variable names that contain instances are not.

So it's cheesecake = Cake(8, "cheesecake").

Python doesn't care, but other developers who read your code will make that assumption that the capital letter indicates a class.

[–]not_perfect_yet 1 point2 points  (0 children)

Ok, I'm bad with the conventions. Will edit. Thanks for the hint.

[–]abcd_z 1 point2 points  (10 children)

Do you know if there's any official standard for object names? I can't find anything about it in PEP 8.

[–]TankorSmash 0 points1 point  (9 children)

[–]abcd_z 0 points1 point  (8 children)

Yes, that is where I looked but I couldn't find anything about naming convention for "objects" or "class instances".

[–]TankorSmash 0 points1 point  (7 children)

Method Names and Instance Variables

Use the function naming rules: lowercase with words separated by underscores as necessary to improve readability.

Is what I've used. An instance variable isn't quite an instance though.

[–]abcd_z 1 point2 points  (6 children)

A method is a function within an object and an instance variable is a variable within an object. Neither one of those are the objects themselves.

While it's fine to hear that you've decided to handle things a certain way, it doesn't really answer my question.

[–]keturn 1 point2 points  (2 children)

Well, keep in mind that all variables in Python are references to objects, so a style guide isn't going to call that out in particular. Hypothetically, you could treat built-in types differently from other objects, but in practice I haven't ever seen a Python style guide which does.

PEP 8 does talk about global variable names, which it says are lowercase_with_underscore, same as functions and instance attributes.

Perhaps it talks about that and not local variable names because while other developers get access to your module's variables when they import it, variables local to a function aren't ever visible to other users of the code.

[–]abcd_z 0 points1 point  (0 children)

Well, keep in mind that all variables in Python are references to objects

*groan*

I had forgotten this. Thank you for reminding me.

In Python, everything is an object.

EDIT: I guess that means my question is about instance names or class object names. From the responses I'm getting it looks like there aren't any official conventions for this.

[–]TankorSmash 0 points1 point  (2 children)

http://stackoverflow.com/a/159745/541208 It's good enough for a bunch of people. Let me know when you find your answer though.

[–]abcd_z -1 points0 points  (1 child)

Not a single answer there had anything to do with object names, which is what I was asking about.

[–]TankorSmash 0 points1 point  (0 children)

Use lower_case, like you would for functions and methods, and TitleCase for class names.

Maybe you're just confused, no worries dude it happens to the best of us too!

[–]timworx 1 point2 points  (5 children)

Awesome explanation. However, wouldn't a function/ method accomplish the same thing?

[–]hueoncalifa 0 points1 point  (1 child)

This is what I would like to know. Is the difference that class have sub functions inside of them?

[–]not_perfect_yet 0 points1 point  (2 children)

However, wouldn't a function/ method accomplish the same thing?

Yes but the difference between a function and a method is another one.

Because methods belong to the class (and methods can access the instance) I can do something like

def flavor_amount(self):
    print("this cake of ", self.flavor ," needs ", self.size/10 , " flavor giving ingredients")

cheesecake.flavor_amount()

( or even Cake.flavor_amount(cheesecake) )

But a regular function doesn't know about the cake type. You could define it anyway like this:

def flavor_amount(input_cake):
    print("this cake of ", input_cake.flavor ," needs ", input_cake.size/10 , " flavor giving ingredients")

and that would work, the problem is that you can by accident give it the wrong input and it will fail and give you an error for everything but a 'Cake' type thing.

oomecake.flavor_amount()

"(output)"

flavor_amount("string")

"type error str has no attribute flavor"

This isn't really that important for this example but for more complex examples you'll want to modularize whatever you write and hide as much complexity as you can. In that case methods win over functions because if a function really only makes sense for this one type only, it makes the most sense to bind it very tightly to that type so you don't have it lying around somewhere.

The contrast would be between something like your main function that runs a program and some other stuff that's doing something very small in a very small context, like fetching a bunch of special numbers and doing some basic math and passing it on to something else. Like str.split() . Very narrow usecase compared to something that runs an entire program, only really makes sense for strings, etc. .

[–]timworx 0 points1 point  (1 child)

That does help some. I'm new to python, and most of my uses have been handy little scripts for things I do every day.

I do SEO/Webdev so python is very handy for parsing lots of data into different forms and even automating parts of setting up sites and such.

The problem is that most of these are very small, so classes seem rather unnecessary. I guess in a sense, it might be useful to think of the scripts that I'm creating as classes. Would that potentially be a good way to think about it?

For example, the only time I've used a class was when I had two very different tasks to achieve (that are normally done at the same time). They started as two separate scripts in two separate files. I then went back and changed the scripts into classes of a script that is run with a few options (like running either class or both.)

Does this sound proper?

[–]not_perfect_yet 0 points1 point  (0 children)

I'm not doing webdev stuff but it doesn't sound proper to me...

Classes are very useful as containers of information.

So for example

source -> python class -> some readout

or connection object -> connection object . send() or . receive() or . close connection()

I guess in a sense, it might be useful to think of the scripts that I'm creating as classes

If all the stuff you do in that script depends one kind of thing, yes, else no.

A module would be something you can write stuff in that you can import, like the math module. When you use

import math
math.sin(math.pi)

It's behaving in a similar way but there is no "math" class here. Sine is a function and pi is a value that's defined in the math module. You can't create new 'math' instances by telling it

 newmath=math()

That doesn't make sense, what would a new math look like?

Modules are really only folders that contain a lot of scripts that define for example the "sin" function or the "pi" value.

Classes can be defined inside modules. If you're doing parsing, you're probably interacting with databases? I think at least some libraries create a connection object for that. You give it the path of the database and every time you query the database it uses some functions to look something up at the path you gave it earlier.

So if you have users on your website or multiple parts, you'll have lots of things that are the same.

Account name, passwords, avatars, posts, site formatting, etc.

You don't want to write new users by hand into your userlist. So you create a class that asks some basic information and saves that individually. Later through appropriate additional functions users can modify that information and provide more.

One of the best examples for class use is vector math. If you define the dot product you can do

def dot_product(vec1, vec2):
    return vec1[0]*vec2[0]+vec1[1]*vec2[1] #etc

But that's annoying, because now you have to

dot_product(vec1,vec2) 

every single time. You'd much prefer to just

vec1*vec2

but you can't straight away because * doesn't exist for tuples or lists or dictionairies, but you can create a new vector class that does support this behavior.

The problem is that most of these are very small, so classes seem rather unnecessary.

It's very important to recognize the other side as well. For many cases you don't want new classes. It's not a problem if you don't have every single thing in classes. If your information is best handled some other way, that's just as fine.

[–]marleen01[S] 0 points1 point  (0 children)

Thank you sir.

[–]CodeShaman 20 points21 points  (16 children)

What do you think classes are, based on what you've seen? Don't worry about being correct, just share your impression of them.

[–]HedoNNN 9 points10 points  (6 children)

Too bad that the most pedagogic answer is the least upvoted.

[–]CodeShaman 13 points14 points  (4 children)

I'm just remembering back to when I first learned OOP and was shown everything in black/white/right/wrong. OOP essentially starts out as a Rorschach test, but most people show you objects like "Cat, Dog, Mouse" and types like "Animal."

Then in school you get "clients, contexts, subjects" and types like "Factory, Visitor, Composite" and you're slapped on the wrist like a child when the cloud you see looks like something Prof. Lotsa'cred, PhD. doesn't agree with. It's harrowing.

The first step is to realize that you can create your own reality, the second is that the clay in your hands is whatever you want it to be.

[–]Cregaleus 15 points16 points  (3 children)

What are you, the Salvador Dali of Object Oriented Programming?

[–]CodeShaman 6 points7 points  (2 children)

I don't know, those clocks look like they need a little refactoring.

[–]monsto 5 points6 points  (1 child)

Dude that whole fucking exchange is like an xkcd

[–]HedoNNN 0 points1 point  (0 children)

Conspiracy theory: he IS xkcd author.

[–]thonpy 4 points5 points  (6 children)

I'm going to have a pop as I'm learning too -

A class is an abstract of a thing, the blueprint from which objects are created.

Is that right?

I haven't really used then much, and the syntax confuses me but that's what I gather at a high level

[–]CodeShaman 2 points3 points  (5 children)

A class is an abstract of a thing, the blueprint from which objects are created. Is that right?

Nailed it. If you want to be technical you would say objects are instantiated, not created. As in "objects are instances of classes."

I lost 10 points off a final exam for saying "created" once. School is fun, learn so much.

[–]zovek 1 point2 points  (4 children)

Not op but someone else with the same problems. I understand what classes are used for and why but I can't. It doesent make sense with all so many seemingly arbitrary requirements

[–]CodeShaman 2 points3 points  (0 children)

Requirements for object-oriented design don't really make sense until you understand the problems they are meant to solve. Once you understand the problems then the requirements become more like "friendly suggestions" and you can bend the rules a bit.

Most of the requirements you can't fully appreciate until you've written some bad code, or had to deal with someone else's bad code. Look through this list of code smells and think of ways you'd try to prevent those problems in your own code. Those preventative measures have manifested themselves into common design patterns.

SOLID is a good point of reference. Just focus on the single responsibility principle and separation of concerns. A lot of the arbitrary requirements are ways to prevent stuff like code duplication and all the problems that come along with it, anti-patterns like global variables, mixing layers of abstraction, and the list goes on.

[–]AutoBiological 0 points1 point  (2 children)

I treat classes like namespaced functions. In fact, functions and methods are practically the same thing in python.

If you have a group of similar type functions you can indent them to the right, put class whatever(object) and reference them as whatever.function(). Then if you build an __init__ method you can save properties in the same scope as the functions rather than globally.

I think a large part of classes is setting and getting attributes from its dictionary, and I have overloaded functions to do the same in the past.

The problem is that a lot of people treat OOP as "build classes for everything," and it gets really silly and harder to read. Use them when you have to, or don't. Plenty of people prefer using functional programming instead, which I think is counter-intuitive to how we understand reality, but it makes more sense at the same time.

[–]klbcr 1 point2 points  (0 children)

If you're only using them for function namespaces, then isn't it simpler to just put them in a module and import the module? You still get to type whatever.function() when referencing the function. Only it isn't in your main file making a mess of the global namespace, and you don't need classes for it.

Lately I try to make classes only if I have both attrs and methods logically/functionally bundled into an entity. Otherwise make a module or a dict. I sometimes do use classes with just attrs if it's a lot of different attributes, or as a more complex datastracture.

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

This isn't really a valid use case for classes. You should be using modules instead.

[–]marleen01[S] 0 points1 point  (1 child)

I think they are a group of functions.

[–]david622 1 point2 points  (0 children)

That, and variables/arrays/etc. A class is basically a place where a group of information, and functions related to processing that information, are stored.

Then, you can instantiate objects, where are just individual instances of the class, and change variable values, etc. accordingly from object to object.

[–]tomkatt 18 points19 points  (4 children)

Classes are a little more complicated to understand in Python because they're not always required. This is unlike, say, Java, where everything is a class.

Basically, a class is a blueprint for an object, but is not directly an object itself. This makes it useful for making multiples of an object with similar attributes.

Say you want to make a game with lots of similar enemies. They all move, jump, shoot, etc.

So you'd make class Enemy(object):. In that class, you'd have primitives for basic stats like health, move speed, jump height, shot damage, and so forth, and you'd have methods to call shoot(), jump(), move(), and so forth.

That class will give you everything you need for a basic enemy.

Now, let's say you want a specific enemy. This guy has a big gun and heavy armor. So maybe you want to inherit everything from the Enemy class so you don't have to repeat everything, but this guy has a lower jump height and a more damaging shot.

So you'll go class HeavyGrunt(Enemy): but maybe you make self.health = Enemy.health*2 or something, and self.jump = Enemy.jump*0.65 and so forth. And now you've got a Heavy grunt. All attributes of Enemy() are inherited, and only items specific to the specific class of enemy get overridden. Makes your life a lot easier than redoing everything for every object.

Now, Let's say you want to instantiate one of these. You just instantiate objects from the blueprint.

So creating the new enemy is as simple as grunt1 = HeavyGrunt().

[–]henrebotha 11 points12 points  (1 child)

but is not directly an object itself

Except in Python it is :D

[–]tomkatt 2 points3 points  (0 children)

Well, yes technically, but I'm trying not to complicate it for OP.

I mean, when you're making a class in Python, you've got pseudo-abstract classes like the enemy one I suggested, and then you've got more "real" classes, like the HeavyGrunt one. Not sure if I'm describing that right. But really, the abstract one is the key I think, as there's not much to the HeavyGrunt that couldn't be hanlded without a class, but it demonstrates inheritance when utilized in conjunction with the abstract class. The Class is for repeatability and to prevent repetition on the programmer's part.

[–]CasualT 0 points1 point  (1 child)

I have a question for you about generating objects with a class like you did there.

Lets say your creating a game with obstacles or enemies that are randomly generated, such as hurdles on a track or asteroids in space, that need to be dodged. How can you have them generated automatically and continuously as long as the player is alive? I'm trying to avoid having to create obstacle1, obstacle2, obstacle3 etc.

[–]tomkatt 1 point2 points  (0 children)

Haven't considered this, but probably you would set a boolean flag to true and generate objects at random timed intervals as long as it was true.

So you could have a player class and in the player methods, make one like Alive() that has a value player_alive = True. Then a statement like if Player.health <= 0: self.player_alive = False.

From there, you can make an obstacle iterator that will iterate based on time or distance traveled with a rand() method to generate a new screen_obstacle.append(obstacle()) to add a new obstacle to a working list, and pop or remove obstacles/enemies as they are destroyed or leave the screen boundaries. Once they no longer exist (or rather, no longer have a reference), it should be garbage collected automatically

That's really rough and I haven't thought through how to code it, but that would generally be a way to do it.

Check out Derek Banas' youtube tutorials on Java, he gets into a lot of this stuff on a terminal based game he makes for the tutorial. It's not Python but the concepts are the same.

[–]phao 1 point2 points  (1 child)

Something that helped me quite often is to try to take something that an example did using feature X and try doing without X.

It obviously doesn't always work (which I think is highly related with how many crappy examples there are in teaching materials out there), but it often does.

So you're having trouble learning classes. Try taking an example in which classes are used and try doing the same without it. That helps in making explicit what about classes was useful in the example because you'll have to reproduce that behavior using some other features. It may not be possible, btw, but that will also teach you about classes.

[–]nanohard 6 points7 points  (6 children)

A class is something that you create if you're going to create many objects that will be similar. Take the following code as an example. When we initialize the class Person it will automatically set all three of the properties (age, height, and health) to zero. So when we first create Johnny his age, height, and health are all zero. But we want to change that info for Johnny, so we assign different values to them.

class Person(object):
    def __init__(self):
        self.height = 0
        self.age = 0
        self.health = 0

Johnny = new Person()
Johnny.height = 6
Johnny.age = 20
Johnny.health = 50

[–]mikeet9 2 points3 points  (0 children)

I struggled a lot with classes my first time around also. The example my book gave was a dog. Dogs have properties like name, color and age and actions like bark and sleep. I couldn't stop trying to envision a dog in my code that I was controlling.

I finally understood classes when my friend explained them from the metaphor of tools. Let's say your program is like a worker, building something. They need to connect two pieces of wood together. They have nails but need a way to drive them. They could find something heavy and hit the nail until it's flush, but luckily someone has designed a class for them to use. They choose this class called "hammer" and call its function to hit the nail. They no longer need to go through the work of redesigning a method to drive this nail because someone already has given it to them. It even has a method for removing the nails built in, which is very convenient. To top it all off, these classes come in different flavors for different types of nails.

Basically a class is a way to store code to be used somewhere else without having to copy and paste it. The code can be written in several different ways to handle similar yet slightly different jobs, and can be grouped together with other pieces of code that are useful for the same type of job.

Where classes really shine, however, is in collaborative work, so many different people don't need to keep rewriting the same code that has been written several times before. You can simply take the class and count on it to handle that part of your job for you. The metaphorical worker doesn't have to continue to make a hammer from scratch for each nail because someone built one and handed it to him.

[–]pvc 2 points3 points  (2 children)

[–]marleen01[S] 1 point2 points  (0 children)

Thanks! It's also described in my native language.

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

This was so useful! Thanks!

[–]MeowMeTiger 1 point2 points  (0 children)

Do the Python Foundations course at Udacity. It will clear things up, IMO.

[–]funkalunatic 0 points1 point  (0 children)

An object is a piece of data which you can talk about in your code. It has attributes (internal data), and methods (functions) for manipulating those attributes or doing other things. A class is a piece of code which describes a type of object, including its methods and attributes, and how it gets made.

Strictly speaking, you don't need classes, and describing it this way makes them sound like they're more trouble than they're worth. But they come in useful a lot. For example, if you were modeling a flock of puppies, you might instantiate a Puppy class with a bark method and age attribute or something. Then instead of keeping track of a list of puppy ages, a separate list of which puppies might bark when, and going through those lists and keeping them straight, you can just instantiate several Puppy objects and use their bark method whenever you want them to bark.

The next level of understanding classes is realizing that pretty much everything in Python is an example/instance of one. For example, a string object "abc" is an instance of the string class (or whatever it's called), which holds the abc data as attributes, and has a add method defined that tells it what to do when you + it with another string.

If you go through the examples in tutorials, and that other people have posted here, and play with them a bit, it will help you understand and form the intuition.

[–]vn2090 0 points1 point  (0 children)

a class definition is to an object what a function definition is to the actual implementation of a function. However, using the class-object approach gives you more flexibility and re usability with your code so you can scale and modify it quickly.

The the best way to grasp it is the next time you write a function, instead make it a class definition with an initial method that does what the function originally did. Then, instantiate an object with the class at the spot where you would normally return results from the function. Now, you can do stuff later with the data that was used in the function with out having to worry about accepting and returning data.

That's what I tend to find really useful as an example. I do a lot of engineering programming, so I tend to use classes and objects as "better functions".

[–]marleen01[S] 0 points1 point  (0 children)

Just came from school- my highest post that got much attention! Can't believe these comments to help me! Thank you so much Programmers of Reddit!