Jump to content

Python 3 Instance vs. Class Variables

Go to solution Solved by fizzlesticks,

To answer the actual question...

self.variable refers to an instance variable inside that instance

ClassName.variable refers to a class variable

So changing

self.unsorted_list

to

__Sorting.unsorted_list

Will make it a class variable.

 

edit: You should probably also change your class name using '_ _' at the start of a class has special meaning that you probably didn't intend to use.

So, I have a project that I like to do for myself every time I'm learning a new language, as it helps me to learn classes and some of the more advanced stuff. The project is to implement different sorting algorithms, and then race them. Sounds simple, and it would be if I didn't make things so hard for myself. 

The problem that I'm having is with the difference between class and instance variables. Specifically, I wish to change a class variable at instantiation. So far, what I have done has caused the variable to be an instance variable. The reason that I want to use a class variable is because I want to easily instantiate all objects of a child class (right now I'm working on the base class) with the same unsorted list (as opposed to passing all instances of child classes the same list at instantiation). In other words, I'm attempting to set myself up in a way that I can be lazy in the future, but hey, who likes to be WET when you could be DRY anyway?

So here is my code:
 

import random
import time

# This program will contain classes that each represent different sorting algorithms and data about the sort.
# The idea is that I can implement different sorting algorithms as classes, pass them all the same lists, and
# receive the sorted list and the time it took to sort the list. First I will implement sorts that I already know
# such as bubble sort, shaker sort, and stooge sort. Then I will branch out into other, more useful, types of sorts.


class __Sorting:
    """This class is the prototype for all other sorting classes \
        It defines things that each class that represents a different sort should have."""

    # A class variable that is shared by all instances of the class/children classes
    unsorted_list = []

    # The constructor. This assigns either nothing or a list to unsorted_list
    def __init__(self, data=None):
        if not data:
            return

        elif type(data) is list:
            self.unsorted_list = list(data)

        else:
            raise ValueError("You must use only an object of type 'list'.")

    # If the user instantiated with a sorted list, we should provide a method to shuffle the list
    def shuffle_unsorted_list(self):
        self.unsorted_list = random.shuffle(self.unsorted_list)


# This is the test, used to determine if unsorted_list is a class or instance variable.
# Turns out, unsorted_list is an instance variable. Why?
my_list = [1, 2, 3]
my_second_list = [4, 5, 6]
test_one = __Sorting(my_list)
test_two = __Sorting(my_second_list)
print(test_one.unsorted_list)
print(test_two.unsorted_list)

What's going on here is that I'm defining the parent class that will simply define things that all of my other classes will share, and things that all of the other classes will implement. The classes will be things like "stupid sort", "bubble sort", "shaker sort", "merge sort"... The classes will have things like: The unsorted list, the sorted list in ascending order, the sorted list in descending order, the time it took to sort ascending, the time it took to sort descending. The classes will do things like sorting a list using the different sorting algorithms that they represent. In other words, class "BubbleSort" will implement the base class method "sort" as a bubble sort, while class "MergeSort" will implement the base class method "sort" as a merge sort.

Now, enough with the background information. What is my actual problem? The code block at the very bottom of the code above, that begins with "my_list = [...]" would print "[4, 5, 6] \n[4, 5, 6]" to the screen if unsorted_list was a class variable. However, it prints "[1, 2, 3] \n[4, 5, 6]" which indicates that unsorted_list is actually an instance variable. Since I want to be lazy later down the road and only have to type "test = <insert>Sort(my_list)" one time (instead of every time I declare a new instance of a child sorting class), how do I turn unsorted_list into a class variable?

ENCRYPTION IS NOT A CRIME

Link to comment
https://linustechtips.com/topic/675187-python-3-instance-vs-class-variables/
Share on other sites

Link to post
Share on other sites

Not really sure you need classes. Personally, I would have each algorithm as a function then have one function you post the too that triggers the other functions.

 

def sorting(list):
	bub = bubble(list)
	sha = shacker(list)
	print(bub)
	print(sha)
	
def bubble(list):
	#sort list
	return list
	
def shacker():
	#sort list
	return list
	
#main
sorting([1,2,3])

or even better have the sorting functions as a package then import that into the main program where you can time execution and what not.

                     ¸„»°'´¸„»°'´ Vorticalbox `'°«„¸`'°«„¸
`'°«„¸¸„»°'´¸„»°'´`'°«„¸Scientia Potentia est  ¸„»°'´`'°«„¸`'°«„¸¸„»°'´

Link to post
Share on other sites

3 minutes ago, vorticalbox said:

Not really sure you need classes. Personally, I would have each algorithm as a function then have one function you post the too that triggers the other functions.

See below:

17 minutes ago, straight_stewie said:

So, I have a project that I like to do for myself every time I'm learning a new language, as it helps me to learn classes and some of the more advanced stuff. The project is to implement different sorting algorithms, and then race them. Sounds simple, and it would be if I didn't make things so hard for myself. 

I very seldom *need* to do things the way I do them, I more regularly do them that way because it will teach me some thing that I need or want to know, in a scenario that interests me.

Your solution would definitely be the easiest and fastest way to race the sorting algorithms, but it wouldn't teach me the things that I'm trying to learn, and while the fun part of the project is racing sorting algorithms, the reason that I'm doing it in the first place is to learn more about classes and <insert python equivalent of C# Func here, I haven't gotten that far yet>

ENCRYPTION IS NOT A CRIME

Link to post
Share on other sites

5 minutes ago, vorticalbox said:

Not really sure you need classes. Personally, I would have each algorithm as a function then have one function you post the too that triggers the other functions.

 

Boo.

 

Do this with composable decorators. Instead of having a Sorter class, make your classes Lists, with the naming of the class indicating the sorting strategy - BubbleSortedList, etc.

 

Another approach is to make a generic SortedList class and have one of the constructor parameters be a SortingStrategy e.g. BubbleSort.

 

You'll probably want to implement the appropriate Abstract Base Class from the collections package in your List implementation. Note that some types of data structures are inherently sorted, such as certain types of trees.

 

https://docs.python.org/3/reference/datamodel.html#emulating-container-types

https://docs.python.org/3/library/collections.abc.html

Link to post
Share on other sites

8 minutes ago, straight_stewie said:

See below:

I very seldom *need* to do things the way I do them, I more regularly do them that way because it will teach me some thing that I need or want to know, in a scenario that interests me.

Your solution would definitely be the easiest and fastest way to race the sorting algorithms, but it wouldn't teach me the things that I'm trying to learn, and while the fun part of the project is racing sorting algorithms, the reason that I'm doing it in the first place is to learn more about classes and <insert python equivalent of C# Func here, I haven't gotten that far yet>

Lets do some specialization here. What do all of your algorithms have in common? 

  1. A timer

You would have to make a sub class for each algorithm in order to get the function you need. Which would save time from writing a timer function for each class or you could do as I suggested and just use functions.

 

1 minute ago, SSL said:

 

Boo.

 

Do this with composable decorators. Instead of having a Sorter class, make your classes Lists, with the naming of the class indicating the sorting strategy - BubbleSortedList, etc.

 

Another approach is to make a generic SortedList class and have one of the constructor parameters be a SortingStrategy e.g. BubbleSort.

 

You'll probably want to implement the appropriate Abstract Base Class from the collections package in your List implementation. Note that some types of data structures are inherently sorted, such as certain types of trees.

 

https://docs.python.org/3/reference/datamodel.html#emulating-container-types

https://docs.python.org/3/library/collections.abc.html

I may be a spoil sport but functions would be less time consuming to create and just as functional.

                     ¸„»°'´¸„»°'´ Vorticalbox `'°«„¸`'°«„¸
`'°«„¸¸„»°'´¸„»°'´`'°«„¸Scientia Potentia est  ¸„»°'´`'°«„¸`'°«„¸¸„»°'´

Link to post
Share on other sites

2 minutes ago, vorticalbox said:

I may be a spoil sport but functions would be less time consuming to create and just as functional.

 

But then you're stuck with imperative, procedural tools. Once you have written these classes, they can be used anywhere; and in an object-oriented, declarative way.

Link to post
Share on other sites

11 minutes ago, SSL said:

 

But then you're stuck with imperative, procedural tools. Once you have written these classes, they can be used anywhere; and in an object-oriented, declarative way.

That may be true but can see any simple way to do this. Guess I need to get my oop work back out from college.

 

edit: so make a sorting class with the construct setting a different sorting?

                     ¸„»°'´¸„»°'´ Vorticalbox `'°«„¸`'°«„¸
`'°«„¸¸„»°'´¸„»°'´`'°«„¸Scientia Potentia est  ¸„»°'´`'°«„¸`'°«„¸¸„»°'´

Link to post
Share on other sites

13 minutes ago, vorticalbox said:

That may be true but can see any simple way to do this. Guess I need to get my oop work back out from college.

 

Part of the problem here is Python itself. Python has a lot of methods for emulating other types, such as numeric types, e.g. __add__. If you want to completely replicate the behavior of List, you need to implement those, which creates extra work. Compare to Java, where the List interface is much more clearly defined, although it is still cluttered with utility methods.

 

Extending the collections.MutableSequence ABC should be sufficient for the OP's needs in this case.  That's just a few methods:

 

__init__ or __new__
__getitem__
__setitem__
__delitem__
__len__
insert

 

Most of those will be one-liners. __getitem__ is the only method that will require any amount of logic, namely the actual business of sorting.

Link to post
Share on other sites

To answer the actual question...

self.variable refers to an instance variable inside that instance

ClassName.variable refers to a class variable

So changing

self.unsorted_list

to

__Sorting.unsorted_list

Will make it a class variable.

 

edit: You should probably also change your class name using '_ _' at the start of a class has special meaning that you probably didn't intend to use.

1474412270.2748842

Link to post
Share on other sites

5 hours ago, fizzlesticks said:

edit: You should probably also change your class name using '_ _' at the start of a class has special meaning that you probably didn't intend to use.

I could be wrong, but doesnt "__" just mean something to the effect of "private" or "do not use"? In which case, that was intended, because my structure would be to implement the actual sorting in other classes which would inherit from this. Is that just completely wrong?

 


 

ENCRYPTION IS NOT A CRIME

Link to post
Share on other sites

1 hour ago, straight_stewie said:

I could be wrong, but doesnt "__" just mean something to the effect of "private" or "do not use"? In which case, that was intended, because my structure would be to implement the actual sorting in other classes which would inherit from this. Is that just completely wrong?

"__" causes name mangling of identifiers within a class which will interfere with using class variables.

If your classes name is "__Sorting" then to write to the "unsorted_list" class variable from inside the class you would have to write

__Sorting.unsorted_list = whatever

however because it starts with "__", that line would get mangled to

_Sorting__Sorting.unordered_list = whatever

and "_Sorting__Sorting" doesn't exist so you would get an error.

 

You can use a single _ which typically means internal or protected if you don't want people to create instances of a class but a private top level class doesn't really make any sense (in any language, not just Python.)

 

1474412270.2748842

Link to post
Share on other sites

2 hours ago, straight_stewie said:

I could be wrong, but doesnt "__" just mean something to the effect of "private" or "do not use"? In which case, that was intended, because my structure would be to implement the actual sorting in other classes which would inherit from this. Is that just completely wrong?

 

What you're looking for is an abstract class, specifically and Abstract Base Class. https://docs.python.org/3/library/abc.html

 

I recommend ditching the randomize method in the interest of separation of concerns. It shouldn't matter if a sorting component is passed an already sorted collection; rather, it should be up to the user to detect and deal with that situation if it occurs. To elaborate on my previous comment where I recommend doing this with composable decorators, you do not need to inherit anything here.

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×