drawing classes

For all coding issues - MODers and programmers, HTML and more.

Moderators: Jeff250, fliptw

Post Reply
User avatar
Isaac
DBB Artist
DBB Artist
Posts: 7736
Joined: Mon Aug 01, 2005 8:47 am
Location: 🍕

drawing classes

Post by Isaac »

Code: Select all


import os,time
from math import sin,cos
class grid:
	def __init__(self,x,y):
		self.x=x
		self.y=y
	def me(self,x,y,character):
		self.xm=int(x)
		self.ym=int(y)
		self.ch=character
		self._draw()
		time.sleep(0.5)
	def decor(self,x,char):
		self.bot=char
		self.xbot=int(x)
	def _build(self,x,y,z):
		xprint=" "
		if x==self.xm and y==self.ym:
			return self.ch
		if y==10:
			return "_"	
		if x<=self.xbot+sin(y)*4+z%10-10:
			return self.bot
		else:
			return xprint
	def _draw(self):
		for z in range (self.y):
			os.system("clear")
			for y in range(self.y):
				print "|",
				for x in range(self.x):
					print self._build(x,y,z),
				print ("|")
plane=grid(40,20)
while 1==1: 
	[[plane.decor(20,")"),plane.me((sin(x)*4+20),(cos(x)*4+10),"8")] for x in range(1000)]
It draws waves moving left and right. It also draws a bee, or number 8, flying around in a circle.

Now, this runs very badly in a terminal window. I run this in regular terminal (ctrl+alt+f1 in ubuntu) for a faster print.

lol... I just typed :w out of habit.

Enjoy my fine art!

edit:
Oh yes! The purpose of this. I'm trying to figure out why people bother with classes, when you can just as easily import whatever you want from a file of functions, which basically acts like a class. This little task is forcing me to think more in classes and I'm starting to see why they're better. However, if you think I'm not really using them correctly, like if you see something that's drifting from oop, let me know! Thanks.
❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉
-⎽__⎽-⎻⎺⎺⎻-⎽__⎽--⎻⎺⎺⎻-★ ·:*¨༺꧁༺ :E ༻꧂༻¨*:·.★-⎽__⎽-⎻⎺⎺⎻-⎽__⎽--⎻⎺⎺⎻-
❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉
User avatar
fliptw
DBB DemiGod
DBB DemiGod
Posts: 6459
Joined: Sat Oct 24, 1998 2:01 am
Location: Calgary Alberta Canada

Re: drawing classes

Post by fliptw »

so you are wondering about object-orientated programming?
User avatar
Isaac
DBB Artist
DBB Artist
Posts: 7736
Joined: Mon Aug 01, 2005 8:47 am
Location: 🍕

Re: drawing classes

Post by Isaac »

In general? It's pretty straight forward I think: Your program draws from functions rather than having every event listed.

I'm really wondering about loose functions vs classes. You see, in Python, both functions and classes use global variables or internal ones. They can be embedded in other functions. You can import a file with a bunch of functions you wrote and make it equal a variable, which has some class like behavior.

tl;dr; classes and functions have enough similarities in python to be almost equals. I'm trying to understand the differences better.

edit: I've started pygame tutorials to get a better understanding of classes.
❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉
-⎽__⎽-⎻⎺⎺⎻-⎽__⎽--⎻⎺⎺⎻-★ ·:*¨༺꧁༺ :E ༻꧂༻¨*:·.★-⎽__⎽-⎻⎺⎺⎻-⎽__⎽--⎻⎺⎺⎻-
❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉
User avatar
Jeff250
DBB Master
DBB Master
Posts: 6530
Joined: Sun Sep 05, 1999 2:01 am
Location: ❄️❄️❄️

Re: drawing classes

Post by Jeff250 »

One of the advantages of classes is that you can instantiate them (like you did above) and have each object instantiation have its own state that it can reference. Another is inheritance and overriding methods.
Isaac wrote:1==1
This is just True, right?
Isaac wrote:[[plane.decor(20,")"),plane.me((sin(x)*4+20),(cos(x)*4+10),"8")] for x in range(1000)]
Don't use list comprehensions only for their side effects! You're building a list of lists of junk in memory for no reason! How about just a for loop like this:

Code: Select all

plane.decor(20, ")")
for x in xrange(1000):
    plane.me((sin(x)*4+20), cos(x)*4+10, "8")
?
User avatar
fliptw
DBB DemiGod
DBB DemiGod
Posts: 6459
Joined: Sat Oct 24, 1998 2:01 am
Location: Calgary Alberta Canada

Re: drawing classes

Post by fliptw »

the form x import y is syntactical sugar: python is importing the class and assigning aliases to the items imported(which may be a object itself) specified.

Classes have data about themselves and methods which they can be changed. they also can be used as the basis for new classes by inheritance.
User avatar
Isaac
DBB Artist
DBB Artist
Posts: 7736
Joined: Mon Aug 01, 2005 8:47 am
Location: 🍕

Re: drawing classes

Post by Isaac »

Jeff250 wrote:One of the advantages of classes is that you can instantiate them (like you did above) and have each object instantiation have its own state that it can reference. Another is inheritance and overriding methods.
But you can also do this when importing a file with modules, no?
I mean if you import mydoc, rather than from mydoc import onemodule.
Then you can x=mydoc and y=mydoc. Then you can x.onemodule(23,22,2) and y.onemodule(33,2,1).
Even pygame has a regular init() module instead of an __init__ method.

As for overridding, this could be done within a new module, just as long as it doesn't effect the other variables, y and x.

But it is more straight forward using classes. I think I like the __init__ better.

Jeff250 wrote:
Isaac wrote:1==1
This is just True, right?
haha yeah. Sorry.
Jeff250 wrote:
Isaac wrote:[[plane.decor(20,")"),plane.me((sin(x)*4+20),(cos(x)*4+10),"8")] for x in range(1000)]
Don't use list comprehensions only for their side effects! You're building a list of lists of junk in memory for no reason! How about just a for loop like this:

Code: Select all

plane.decor(20, ")")
for x in xrange(1000):
    plane.me((sin(x)*4+20), cos(x)*4+10, "8")
?
Hhahah! Yeah. That should have been obvious to me.
❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉
-⎽__⎽-⎻⎺⎺⎻-⎽__⎽--⎻⎺⎺⎻-★ ·:*¨༺꧁༺ :E ༻꧂༻¨*:·.★-⎽__⎽-⎻⎺⎺⎻-⎽__⎽--⎻⎺⎺⎻-
❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉
User avatar
fliptw
DBB DemiGod
DBB DemiGod
Posts: 6459
Joined: Sat Oct 24, 1998 2:01 am
Location: Calgary Alberta Canada

Re: drawing classes

Post by fliptw »

Isaac wrote:
Jeff250 wrote:One of the advantages of classes is that you can instantiate them (like you did above) and have each object instantiation have its own state that it can reference. Another is inheritance and overriding methods.
But you can also do this when importing a file with modules, no?
you should read up on object orientated programming. importing is a different concept than OOP.
User avatar
Jeff250
DBB Master
DBB Master
Posts: 6530
Joined: Sun Sep 05, 1999 2:01 am
Location: ❄️❄️❄️

Re: drawing classes

Post by Jeff250 »

Isaac wrote:I mean if you import mydoc, rather than from mydoc import onemodule.
Then you can x=mydoc and y=mydoc. Then you can x.onemodule(23,22,2) and y.onemodule(33,2,1).
Even pygame has a regular init() module instead of an __init__ method.
Let's try this...

Code: Select all

# foo.py

params = {'x': None, 'y': None, 'z': None}

def set_xyz(x, y, z):
    params['x'] = x
    params['y'] = y
    params['z'] = z
    
def get_xyz():
    return params['x'], params['y'], params['z']

Code: Select all

>>> import foo
>>> x = foo
>>> y = foo
>>> x.set_xyz(1, 2, 3)
>>> y.set_xyz(4, 5, 6)
>>> x.get_xyz()
(4, 5, 6)
>>> y.get_xyz()
(4, 5, 6)
What if you want x and y to have separate state?
User avatar
Isaac
DBB Artist
DBB Artist
Posts: 7736
Joined: Mon Aug 01, 2005 8:47 am
Location: 🍕

Re: drawing classes

Post by Isaac »

Oh crap.. Wow thanks! Ok that clears it up really well!
❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉
-⎽__⎽-⎻⎺⎺⎻-⎽__⎽--⎻⎺⎺⎻-★ ·:*¨༺꧁༺ :E ༻꧂༻¨*:·.★-⎽__⎽-⎻⎺⎺⎻-⎽__⎽--⎻⎺⎺⎻-
❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉
User avatar
snoopy
DBB Benefactor
DBB Benefactor
Posts: 4435
Joined: Thu Sep 02, 1999 2:01 am

Re: drawing classes

Post by snoopy »

Funny...

In my recent reading on python I hadn't gotten a really clear understanding of modules & functions vs. classes. Mostly, because I hadn't read the documentation on classes very carefully yet.

Discussions like this prove to be useful! It appears that you can, in fact, conveniently choose between the two specifically depending upon how you want Jeff's example to behave.
Arch Linux x86-64, Openbox
"We'll just set a new course for that empty region over there, near that blackish, holeish thing. " Zapp Brannigan
User avatar
Isaac
DBB Artist
DBB Artist
Posts: 7736
Joined: Mon Aug 01, 2005 8:47 am
Location: 🍕

Re: drawing classes

Post by Isaac »

Yeah. What I see is, if values are going to be stored in a file like foo you will have a result like Jeff's example. If you want variables in the imported file to be their own instance then use classes or be sure to include a delete function. Classes will be easier.
❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉
-⎽__⎽-⎻⎺⎺⎻-⎽__⎽--⎻⎺⎺⎻-★ ·:*¨༺꧁༺ :E ༻꧂༻¨*:·.★-⎽__⎽-⎻⎺⎺⎻-⎽__⎽--⎻⎺⎺⎻-
❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉
User avatar
snoopy
DBB Benefactor
DBB Benefactor
Posts: 4435
Joined: Thu Sep 02, 1999 2:01 am

Re: drawing classes

Post by snoopy »

I haven't (thus far) gotten to the point where I think some global variables are the better way to go, so I haven't really learned the python global variable thing yet.

So far, I have one variable that I'm passing most of the time, but that's not even *all the time.* My memory of programming mojo is that global variables should be generally avoided unless they are really a variable that's globally used. For one part, having global variables makes it harder to test individual modules/functions/classes because you have to do the proper global variable configuration before you can run the function with success.

If you just make sure that you pass *everything* that function needs, then a 1-line invocation in the interpreter would suffice to test it.
Arch Linux x86-64, Openbox
"We'll just set a new course for that empty region over there, near that blackish, holeish thing. " Zapp Brannigan
User avatar
Isaac
DBB Artist
DBB Artist
Posts: 7736
Joined: Mon Aug 01, 2005 8:47 am
Location: 🍕

Re: drawing classes

Post by Isaac »

In my example, I believe "gl" is a global variable because it can be used by any function in the script.

Code: Select all

>>> gl=3
>>> def bb(loc):
...     return gl+loc
... 
>>> bb(3)
6
>>> 
The local variable "loc", however, is invisible to anything written outside the internals of bb().

You can also use the "global" syntax to specify your variable is global, assuming a variable was first defined within the function or class. I never use it, though. In a class you can call any variable, assuming you don't hide it with "_" in front. like

Code: Select all

_hidden=3
amrite?
❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉
-⎽__⎽-⎻⎺⎺⎻-⎽__⎽--⎻⎺⎺⎻-★ ·:*¨༺꧁༺ :E ༻꧂༻¨*:·.★-⎽__⎽-⎻⎺⎺⎻-⎽__⎽--⎻⎺⎺⎻-
❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉
User avatar
snoopy
DBB Benefactor
DBB Benefactor
Posts: 4435
Joined: Thu Sep 02, 1999 2:01 am

Re: drawing classes

Post by snoopy »

I don't know the correct terminology for this, but I don't think gl in your example is really a global variable, it's a variable that belongs to the "terminal" module (whatever you call it) and since you're defining bb within the "terminal" module as well, it knows what gl is.

(I can test this tonight but don't have access to the python interpreter right now.)

If you do this:

Code: Select all

bb.py

def bb(loc):
    return gl+loc

And then in the interpreter:

Code: Select all

>>> import bb
>>> gl=3
>>> bb.bb(3)

Error: bb doesn't know what gl is!
>>>
However, if you did:

Code: Select all

bb.py

gl=3

def bb(loc):
    return gl+loc

def cc(loc):
    return gl*loc

And then in terminal:

Code: Select all

>>> import bb
>>> gl=25
>>> bb.bb(3)
6
>>> bb.cc(3)
9
>>>
I.E. you can define "gl" multiple places, but each value stays with the module within which it was defined... that you you don't have to worry about variables stepping on each other from module to module.

By a global variable I mean everything would use the same "gl" and if you change it in module x, then module y will operate on the changed value... if you aren't really careful to keep track of "gl" being global, you can accidentally change it and then mess something else up. Also, if you want to test your module stand-alone, and within the module your global variable isn't defined, you have to remember to define the global variable, as a global variable, every time before you try to run your module, which is a pain.

For my program, I'm thinking of a "program_path" variable. A lot of my functions are going to want to know what the program_path variable is, and it's going to be the same value for every function - is that something that makes sense to make a global variable? If so, is there a convenient way to define it so I don't have to manually define it each time I want to test an individual module from the interpreter?

Four possible answers that I can think of:
1. For particularly this case, would it work to make the program cd to my program path, and then just have all of my modules use the working path instead of some external variable?
2. Write a module/class/function that does the leg work to figure out the path, and invoke it each time I need to know the path
3. Write a module/class/function that does the leg work to figure out the path and define it as a global variable, then make each module invoke it during initialization if the variable is unknown.
4. Just pass the path to the function when you call the function

I think there's a way to do any of them, but I don't know which approach would be the most efficient from a time/memory standpoint.
Arch Linux x86-64, Openbox
"We'll just set a new course for that empty region over there, near that blackish, holeish thing. " Zapp Brannigan
User avatar
Isaac
DBB Artist
DBB Artist
Posts: 7736
Joined: Mon Aug 01, 2005 8:47 am
Location: 🍕

Re: drawing classes

Post by Isaac »

Just to be clear, you're saying you'll be using mymainloop.__file__ to first define the main location of your app, then put that value into a variable called program path, so that every part of your program will know where it's "head" is.

Right? Remember I'm a slow DBBer.
❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉
-⎽__⎽-⎻⎺⎺⎻-⎽__⎽--⎻⎺⎺⎻-★ ·:*¨༺꧁༺ :E ༻꧂༻¨*:·.★-⎽__⎽-⎻⎺⎺⎻-⎽__⎽--⎻⎺⎺⎻-
❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉❉⊱•═•⊰❉⊱•═•⊰❉⊱•═•⊰❉
User avatar
Jeff250
DBB Master
DBB Master
Posts: 6530
Joined: Sun Sep 05, 1999 2:01 am
Location: ❄️❄️❄️

Re: drawing classes

Post by Jeff250 »

snoopy wrote:By a global variable I mean everything would use the same "gl" and if you change it in module x, then module y will operate on the changed value...
In python, "global" means global to the module. There's no inter-module global without referencing the module (to prevent modules from clobbering each other's variables). So if

Code: Select all

# main.py
. . .
DIRNAME = os.path.dirname(__file__)
. . .
Then you just say in any module

Code: Select all

import main
. . .
main.DIRNAME
or

Code: Select all

from main import DIRNAME
. . .
DIRNAME
User avatar
Jeff250
DBB Master
DBB Master
Posts: 6530
Joined: Sun Sep 05, 1999 2:01 am
Location: ❄️❄️❄️

Re: drawing classes

Post by Jeff250 »

snoopy wrote:Discussions like this prove to be useful! It appears that you can, in fact, conveniently choose between the two specifically depending upon how you want Jeff's example to behave.
There's also an "art" to it as well. For instance, the idea of singleton classes really throws a monkey wrench at my example.

Modules are ways to organize related global variables, functions, and *classes* (so the two aren't even mutually exclusive).

Classes are things like "Person" or "Location" or "Color" or "Connection" whose object instantiations semantically refer to objects. A "Person" or "Location" or "Color" or "Connection" seem like actual "things."
User avatar
snoopy
DBB Benefactor
DBB Benefactor
Posts: 4435
Joined: Thu Sep 02, 1999 2:01 am

Re: drawing classes

Post by snoopy »

Issac: Yes, that was the idea. Though, when I think about it, it may actually be minimally necessary - to the point where it just makes sense to pass it as a function variable. One example of when I'm using it is when I'm trying to read config files: I try to read from the user's home directory first, then fall back to /etc/, and finally fall back to the program path.

Beyond that, there probably aren't going to be a whole lot of instances where it's going to be used, since all of the data that's written to the drive shouldn't reside in the program path... just canned template configuration files that would be transferred prior to actual usage. In fact... maybe I should make my config file read function fail after the second path (/etc) and just complain to the user about needing to copy config files appropriately.

Jeff: I suppose that this is the most efficient way to do it?
Arch Linux x86-64, Openbox
"We'll just set a new course for that empty region over there, near that blackish, holeish thing. " Zapp Brannigan
User avatar
Jeff250
DBB Master
DBB Master
Posts: 6530
Joined: Sun Sep 05, 1999 2:01 am
Location: ❄️❄️❄️

Re: drawing classes

Post by Jeff250 »

I don't know what you mean by most efficient, but your plan sounds good to me.
Post Reply