Planet sim and Etch added, working properly AFAIK

This commit is contained in:
ben 2022-07-19 16:40:55 -05:00
commit 88f86dc04f
19 changed files with 638 additions and 0 deletions

3
.idea/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

View file

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

4
.idea/misc.xml Normal file
View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (thesaurus)" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/python_notes.iml" filepath="$PROJECT_DIR$/.idea/python_notes.iml" />
</modules>
</component>
</project>

8
.idea/python_notes.iml Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 3.10 (thesaurus)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

7
.idea/vcs.xml Normal file
View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="svn" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

57
Classes and OOP/cat.py Normal file
View file

@ -0,0 +1,57 @@
import random
import time
from pet import Pet
class Cat(Pet):
def __init__(self, name='Garfield', color='brown', breed='cat',
chance_of_overthrowing_major_world_government=100): # self is equivalent of this
"""
Initializes instance of Dog class.
:param color: color of Dog
:param breed: breed of Dog
:param chance_of_overthrowing_major_world_government: the chance of the Cat overthrowing world governments
"""
# Can add __ before variable name to make it a private
# variable, so it can't be directly accessed. Only through methods.
super().__init__(name, color, breed)
self.__chance_of_overthrowing_major_government = chance_of_overthrowing_major_world_government
@property
def chance_of_overthrowing_major_government(self):
return self.__chance_of_overthrowing_major_government
@staticmethod
def __meow():
print('meow, meow')
@staticmethod
def __purr():
print('*vibration noise between approximately 25 hz and 150 hz*')
@staticmethod
def laser():
Cat.__meow()
print('*pounce*')
time.sleep(1)
print('*pounce pounce*')
def __str__(self):
return f'{super().name} is a {super().color} {super().breed} that has a ' \
f'{self.__chance_of_overthrowing_major_government}% chance of overthrowing a major government.'
def __eq__(self, other):
if not isinstance(other, Cat):
raise TypeError
if self.color == other.__color and self.__breed == other.__color and \
self.__chance_of_overthrowing_major_government == other.__color:
return True
return False
@staticmethod
def make_noise():
num = random.randint(0, 1)
if num == 0:
Cat.__meow()
else:
Cat.__purr()

View file

@ -0,0 +1,73 @@
### Object Oriented Programming (OOP)
- Object definition: An object is an instance of a class
- For example, `str` is not an object, but in `word = 'hi'` word is an object (an instance of the `str` class)
- Objects use allocated memory
- A physically entity (digitally). You can't hold it, but an object is a thing. A class is an idea for how to make an object.
- Characteristic/Attributes objects have
- Identity
- Each object has its own identity, such as a memory address. Two variables may reference the same object, but the identity is the memory address of the object.
- State
- The state is all the attributes of the object with values assigned to them. Such as a plane object having a fuel object. Anytime you change the fuel object, you change the plane object's state.
- Behavior
- Example: \_\_eq\_\_ method in `str`.
- Always use behavior to access state (getter and setters), don't access directly.
- Class definition: A class is the code that instructs a program how a particular object should be built.
- A class is used to create many objects.
- OOP Characteristics:
- Encapsulation
- Class, variable, getter, and setter all in one thing.
```
class Cookie:
def __init__(self):
self.flavor = flavor
def get_flavor(self):
return self.flavor
def set_flavor(self, flavor):
self.flavor = flavor
```
- Abstraction (user interface vs private interface)
- `.sort()` does stuff, you make it easy, and you don't care how it does it (as long as it's reasonably efficient).
- Inheritance
- is-a relationship
- Ferrari is-a Car
- Can use methods of parent class, such as `__str__`, and add on to it with its own `__str__`.
- Polymorphism
- Always used with inheritance.
- Overriding a parent class's method with a different method with different or extra functionality.
- In the Ferrari class, `__str__()` overrides the Car `__str__()`, and can provide extra functionality, such as multiplying the cost to repair because it's a Ferrari.
### Classes
- Magic methods (also called dunder methods) (override methods):
- If: `__eq__(), __gt__(), __ge__(), __lt__(), __le__(), __and__(), __or__()`
- Math `__add__(), __abs__(), __ceil__(), __sub__(), __mod__(), __mul__(), __round__(), __floordiv__()`
- Make vars private by adding '__' to the beginning of the variable name
- getters and setters are good, or you can make @property, @var_name.setter, etc functions
```
# Acts as a getter, but is used for class_name.color
@property
def color(self):
return self.__color
@color.setter
def color(self, value):
self.color = value
```
- Inheritance
- How to make inheritance in Python: `class Dog(Pet): # Dog inherits from Pet`
- Basic explanation of inheritance in OOP section.
- Arbitrary parameters
- Arbitrary num of parameters for a function/method
- Can use `*args` or `**kwargs` to get a tuple or dict with an arbitrary length
- Variable name doesn't actually matter those names are standard, just number of asterisks *. 1 for tuple, 2 for dict.
- Example:
```
def custom_sum(*args):
total = 0
for num in args:
total += num
return total
print(custom_sum(1, 2, 3, 4, 5, 6, 7, 8, 9))
```

View file

@ -0,0 +1,66 @@
from dog import Dog # Imports class from other python file (dog.py)
from cat import Cat
# dog1 and dog2 are variables holding reference to instance of Dog in heap
dog1 = Dog(color='blue')
dog2 = Dog(weight=15.7)
dog3 = Dog(breed='beagle', weight=15.7)
# Calls __str__()
print(dog1)
print(dog2)
# Calls __eq__()
print(dog1 == dog2)
# Also calls __eq__()
print(dog1 != dog2)
dog1.name = 'snow'
print(dog1.color)
dog1.name = 'light'
print(dog1.color)
# Is type "class '__main__.Dog'"
print(type(dog1), type(dog2))
# You can do these, but you shouldn't. It's not good for OOP
# Commenting out because it's a mess
# dog1.breath = 'bad'
# print(dog1.breath)
# for attribute in dir(dog1):
# print(f'{attribute}: {dog1.__getattribute__(attribute)}')
num1 = 42
num2 = 99
if num1 == num2:
print('Equal')
else:
print('Not equal')
print(dog2)
print(dog3)
print(dog2 == dog3)
dog1.do_something(item='newspaper')
# Cat
print()
cat1 = Cat(color='heliotrope')
print(cat1)
cat1.laser()
cat1.make_noise()
print()
# Other stuff
def get_full_name(*args): # Can be any name, as long as it starts with *.
full_name = ''
for name in args:
full_name += name + ' '
return full_name[:-1]
print(get_full_name('super', 'cali', 'fragilistic', 'expialidocious'))

50
Classes and OOP/dog.py Normal file
View file

@ -0,0 +1,50 @@
from pet import Pet
class Dog(Pet):
def __init__(self, name='Odie', color='brown', breed='poodle', weight=25.0): # self is equivalent of this
"""
Initializes instance of Dog class.
:param name: name of Dog
:param color: color of Dog
:param breed: breed of Dog
:param weight: weight of Dog
"""
super().__init__(name, color, breed)
# Can add __ before variable name to make it a private
# variable, so it can't be directly accessed. Only through methods.
self.__weight = weight
self.__bark()
@staticmethod
def __bark():
"""
woof
:return: None
"""
print('woof woof')
@property
def weight(self):
return self.__weight
@weight.setter
def weight(self, weight):
self.__weight = weight
def __str__(self):
return f'{self.name} {self.color} {self.breed} that weighs {self.__weight}.'
def __eq__(self, other):
if not isinstance(other, Dog):
raise TypeError
if super().color == other.color and super().breed == other.breed and self.__weight == other.__weight:
return True
return False
def do_something(self, **kwargs):
if 'item' in kwargs:
self.__bark()
print(f"Here's a {kwargs['item']}")
else:
print('*confusion*')

23
Classes and OOP/pet.py Normal file
View file

@ -0,0 +1,23 @@
class Pet:
def __init__(self, name, color, breed):
self.__name = name
self.__color = color
self.__breed = breed
# Can do this to make variables private, but look like public
@property
def name(self):
return self.__name
@name.setter
def name(self, name):
self.__name = name
@property
def color(self):
return self.__color
@property
def breed(self):
return self.__breed

View file

@ -0,0 +1,101 @@
from turtle import Turtle, mainloop
class Etch:
def __init__(self):
self.__t = Turtle()
self.__screen = self.__t.screen
self.__color_list = ['#35b070', 'black', 'white', 'red', 'orange', 'yellow', 'green', 'blue', 'purple', 'pink']
self.__color_index = 0
self.__t.color(self.__color_list[self.__color_index])
self.__t.pensize(1)
self.__t.speed(0)
self.__distance = 10
self.__turn = 10
# Add callbacks
self.__screen.onkey(self.__fwd, 'w')
self.__screen.onkey(self.__back, 's')
self.__screen.onkey(self.__left, 'a')
self.__screen.onkey(self.__right, 'd')
self.__screen.onkey(self.__increase_distance, 'e')
self.__screen.onkey(self.__decrease_distance, 'q')
self.__screen.onkey(self.__increase_turn, 'r')
self.__screen.onkey(self.__decrease_turn, 'f')
self.__screen.onkey(self.__toggle_pen, 'z')
self.__screen.onkey(self.__color, 'c')
self.__screen.onkey(self.__clear, 'x')
self.__screen.onkey(self.__quit, 'Escape')
self.__screen.listen()
def main(self):
mainloop()
# Callback methods
def __increase_distance(self):
if self.__distance == 100:
pass
elif self.__distance < 5:
self.__distance += 1
else:
self.__distance += 5
def __decrease_distance(self):
if self.__distance == 1:
pass
elif self.__distance <= 5:
self.__distance -= 1
else:
self.__distance -= 5
def __increase_turn(self):
if self.__turn == 180:
pass
elif self.__turn < 5:
self.__turn += 1
else:
self.__turn += 5
def __decrease_turn(self):
if self.__turn == 1:
pass
elif self.__turn <= 5:
self.__turn -= 1
else:
self.__turn -= 5
def __fwd(self):
self.__t.forward(self.__distance)
def __back(self):
self.__t.backward(self.__distance)
def __left(self):
self.__t.left(self.__turn)
def __right(self):
self.__t.right(self.__turn)
def __toggle_pen(self):
if self.__t.isdown():
self.__t.penup()
else:
self.__t.pendown()
def __clear(self):
self.__t.clear()
def __color(self):
if self.__color_index == 9:
self.__color_index = -1
self.__color_index += 1
self.__t.color(self.__color_list[self.__color_index])
def __quit(self):
exit(0)
if __name__ == '__main__':
draw = Etch()
draw.main()

View file

@ -0,0 +1,3 @@
### Planet Simulator
A very basic planet simulator. Really just a demo of using classes with turtle.

View file

@ -0,0 +1,56 @@
import math
import turtle
class Planet:
def __init__(self, name, radius, mass, distanceFromSun, velocity, color):
"""
initializes the Planet
:param name: name of planet
:param radius: radius of planet
:param mass: mass of planet
:param distanceFromSun: distance of planet from the sun
:param velocity: tuple containing the velocity of the planet in the format (x_velocity, y_velocity)
:param color: color of planet
"""
self.__name = name
self.__radius = radius
self.__mass = mass
self.__distance = distanceFromSun
self.__velocity = velocity
self.__color = color
self.__coords = [distanceFromSun, 0]
self.__pT = turtle.Turtle()
self.__pT.pensize(1)
self.__pT.color(self.__color)
if name == 'earth' or name == 'Earth':
self.__pT.shape('turtle')
else:
self.__pT.shape('circle')
self.__pT.up()
self.__pT.goto(self.__coords[0], self.__coords[1])
self.__pT.down()
def moveTo(self, new_coords):
self.__coords = new_coords
self.__pT.goto(self.__coords[0], self.__coords[1])
@property
def velocity(self):
return self.__velocity
@velocity.setter
def velocity(self, vel):
self.__velocity = vel
@property
def coords(self):
return self.__coords
@coords.setter
def coords(self, new_coords):
self.__coords = new_coords
def __str__(self):
return f'{self.__name} at distance {self.__distance}'

View file

@ -0,0 +1,29 @@
from sun import Sun
from solar_system import SolarSystem
from planet import Planet
# Create a SolarSystem
solar_sys = SolarSystem(2, 2)
# Create sun
sun = Sun('Sun', 5000, 40, 1000)
solar_sys.add_sun(sun)
# Create planets
p = Planet('Mercury', 1, 500, 0.15, (0, 2), 'black')
solar_sys.add_planet(p)
p = Planet('Venus', 1, 500, 0.25, (0, 2), 'purple')
solar_sys.add_planet(p)
p = Planet('Earth', 1, 700, 0.5, (0, 2), '#2152a6')
solar_sys.add_planet(p)
p = Planet('Mars', 1, 700, 0.6, (0, 2), '#b32b10')
solar_sys.add_planet(p)
solar_sys.show_planets()
num_time_periods = 1000
for _ in range(num_time_periods):
solar_sys.move_planets()
solar_sys.freeze()

View file

@ -0,0 +1,50 @@
import turtle
import math
class SolarSystem:
def __init__(self, width, height):
"""
initializes SolarSystem
:param width: width of world
:param height: height of world
"""
self.__theSun = None
self.__planets = []
self.__screen = turtle.Screen()
self.__screen.setup(width=950, height=950)
self.__screen.setworldcoordinates(-width / 2, -height / 2, width / 2, height / 2)
def move_planets(self):
G = 0.025
dt = 0.001
for p in self.__planets:
p.moveTo((p.coords[0] + dt * p.velocity[0], p.coords[1] + dt * p.velocity[1]))
radius_x = self.__theSun.x - p.coords[0]
radius_y = self.__theSun.y - p.coords[1]
radius = math.sqrt((radius_x ** 2) + (radius_y ** 2)) # Uses pythagorean theorem to find radius
acc_x = G * self.__theSun.mass * radius_x / radius ** 3 # I don't know,
acc_y = G * self.__theSun.mass * radius_y / radius ** 3 # I haven't taken physics
p.velocity = (p.velocity[0] + dt * acc_x, p.velocity[1] + dt * acc_y)
def add_sun(self, sun):
self.__theSun = sun
def add_planet(self, planet):
self.__planets.append(planet)
def remove_planet(self, planet_name):
for p in self.__planets:
if p.name == planet_name:
self.__planets.remove(p)
def show_planets(self):
for p in self.__planets:
print(p)
def freeze(self):
self.__screen.exitonclick()

67
Turtle/PlanetSim/sun.py Normal file
View file

@ -0,0 +1,67 @@
import math
import turtle
class Sun:
def __init__(self, name, radius, mass, temp):
"""
initializes Sun
:param name: name of Sun
:param radius: radius of Sun
:param mass: mass of Sun
:param temp: temperature of Sun
"""
self.__name = name
self.__radius = radius
self.__mass = mass
self.__temp = temp
# List of coordinates in order of [x, y]
self.__coords = (0, 0)
self.__sunT = turtle.Turtle()
self.__sunT.shape('circle')
self.__sunT.color('orange')
self.__sunT.shapesize(2)
@property
def name(self):
return self.__name
@property
def x(self):
return self.__coords[0]
@property
def y(self):
return self.__coords[1]
@property
def mass(self):
return self.__mass
@property
def radius(self):
return self.__radius
@property
def temperature(self):
return self.__temp
@property
def volume(self):
return (4 / 3) * math.pi * (self.__radius ** 3)
@property
def surface_area(self):
return 4 * math.pi * (self.__radius ** 2)
@property
def density(self):
return self.__mass / self.volume
@name.setter
def name(self, name):
self.__name = name
def __str__(self):
return f'{self.__name} at ({self.__coords[0]}, {self.__coords[1]})'

11
Turtle/turtle.md Normal file
View file

@ -0,0 +1,11 @@
### Turtle
##### [Turtle documentation](https://docs.python.org/3/library/turtle.html)
- What is turtle?
- Imagine you control a robotic turtle (default is actually a black triangle) which moves around on screen.
- You draw lines, like a digital etch-a-sketch (but you can lift the "pen" off the screen)
- For example:
- Move forward: `turtle.forward(num_pixels)`
- Turn right: `turtle.right(degrees)`
- For usage of turtle, look in Etch class. It's pretty self-explanatory.

16
main.py Normal file
View file

@ -0,0 +1,16 @@
# This is a sample Python script.
# Press Shift+F10 to execute it or replace it with your code.
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.
def print_hi(name):
# Use a breakpoint in the code line below to debug your script.
print(f'Hi, {name}') # Press Ctrl+F8 to toggle the breakpoint.
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
print_hi('PyCharm')
# See PyCharm help at https://www.jetbrains.com/help/pycharm/