This is question based on the shapely package but I think it's a more general question.
Basically I have two classes coming from shapely. One is called Point and the other is called MultiPoint. You instantiate Point with a tuple of coordinates and MultiPoint with a list of Point. You can access the points in multipoint using indexing.
p1 = Point((1,1))
p2 = Point((2,2))
mp = MultiPoint([p1,p2])
In [315]: MultiPoint((p1, p2))[0]
Out[315]: <shapely.geometry.point.Point at 0x1049b1f50>
I want to subclass Point and use it for the location of a car.
class Car(Point):
def __init__(self, coords, speed):
super(self.__class__, self).__init__(coords)
self.speed = speed
Now I can write
c1 = Car((1,1), speed=2)
c2 = Car((2,2), speed=3)
mc = MultiPoint([c1,c2])
I can access the cars using indexing but they are no longer cars. They are points. In particular they have no attribute speed.
In [316]: MultiPoint((c1, c2))[0]
Out[316]: <shapely.geometry.point.Point at 0x1049b1610>
In [317]: MultiPoint((c1, c2))[0].speed
AttributeError: 'Point' object has no attribute 'speed'
Is there a way of fixing this by subclassing Multipoint? I guess I don't know what happens to cars (points) when they are passed to MultiPoint.
Edit: I made a mistake typing the code example for c1 and c2. It's fixed now. I wasn't instantiating points, I was instantiating cars.
While the MultiPoint class is conceptually a collection of Points, it's not actually keeping a reference to the Point instance (or instances of a Point subclass) that you pass in to its constructor. Rather, it copies the coordinates from the point into its own internal data structure. This loses the extra attributes you've added to your Car subclass. Here's the brief passage in the docs:
The constructor also accepts another MultiPoint instance or an unordered sequence of Point instances, thereby making copies.
I'd suggest designing your Car class to have an attribute that is a Point (or maybe a reference to a MultiPoint and an index), rather than making it be a subclass of Point. Inheriting from another conceptually unrelated type is usually a bad idea when you can use encapsulation instead.
It can help clarify your design to remember that inheritance means "IS-A", while encapsulation means "HAS-A". For instance, a rectangle IS-A shape, so if you write a Shape class, a Rectangle would be a perfectly reasonable subclass. In your case, your inheritance suggests that a Car IS-A Point, which doesn't make much sense. It would make more sense to say that a Car HAS-A position (which is a Point).
You should instantiate the Car objects with the Car class constructor:
c1 = Car((1,1), speed=2)
c2 = Car((2,2), speed=3)
mc = MultiPoint([c1,c2])
Python follows the duck typing principle:
If it quacks like a duck and looks like a duck, then it must be a
duck.
This makes Polymorphism very easy. Your objects are not any particular class, they behave according to their superclasses. This behaviour can be different in different circumstances.
Your MultiPoint class will glady accept Car objects in place of Point objects.
I'm curious about your Point class, could you post it?
The problem is here:
c1 = Point((1,1), speed=2)
c2 = Point((2,2), speed=3)
mc = MultiPoint([c1,c2])
According to the description you had to instantiate Car objects, not Points:
c1 = Car((1,1), 2)
c2 = Car((2,2), 3)
Related
Basically I want to have two classes Trades and HistoricalTrades. The second one would be a copy of the first with few more attributes. The Trades instances would be deleted after I get copies on HistoricalTrades
I have solved this by passing attributes manually.
class Trades:
...
class HistoricalTrades:
...
k = Trades(price=123, amount=10)
h = HistoricalTrades(price=k.price, amount=k.amount, sell_date=k.sell_date)
k.delete()
It kinda works as expected but I feel it is not elegant. Is there any other (better) way to move class instance to other class?
For this specific case, assuming no use of __slots__, and that the three attributes used are in fact the sole attributes of Trade, you could get away with a small cheat, changing:
h = HistoricalTrades(price=k.price, amount=k.amount, sell_date=k.sell_date)
to:
h = HistoricalTrades(**vars(k))
vars(k) returns the __dict__ of k itself, which we then unpack with ** into the name/value pairs as the keyword arguments to initialize HistoricalTrades with.
That solution is a little kludgy (as noted, it depends on not using __slots__ and not having any other attributes). Really, the nice way to do this is to define an alternate constructor for HistoricalTrades that does the slog work for you, simplifying use for the caller:
class HistoricalTrades:
...
#classmethod
def from_trade(cls, trade):
return cls(price=trade.price, amount=trade.amount, sell_date=trade.sell_date)
Yeah, it's the same code, but it's written once, and every call site can simplify to:
h = HistoricalTrades.from_trade(k)
which is both concise and self-documenting.
Inheritance sounds useful here:
class Trades:
...
class HistoricalTrades(Trades): # This will make HistoricalTrades inherit characteristics from Trades
...
h = HistoricalTrades(price=123, amount=10, sell_date="Some data not provided")
But I think more information would be needed for us to provide you with a more appropriate answer...
First of all, I am a total newbie. Thanks for your patience.
I am designing a piece of software to calculate insulation materials and amounts on different houses.
I have a class House(), which holds attributes like roof_area and wall_area.
I have a class Insulator(), which holds attributes like thickness and area (the area the packaged material covers)
Now I want to know how many packages of the insulator I should buy in order to cover the whole roof area.
So, the operation would be:
House.roof_area / Insulator.area = insulator_packages_needed_for_roof
The thing is I can't do that operation:
AttributeError: type object 'House' has no attribute 'roof_area'.
Of course I could do it a an instance scope, but I don't want to specify an instance yet, as this operation should be done for any instance of the Class that gets build in the future. Should I use inheritance? My feeling is that, given that Insulator and House are totally different things, they shouldn't be mixed by inheritance, but I am just a beginner.
It doesn't make any sense to try to compute the number of insulation packages you need to cover the roof of a house, without using any instances of your House or Insulator classes. It only makes sense if you have one instance of each.
You can, however, write the code to do the calculation before you've created the instances. Just put it in a function that takes the instances as arguments:
def roof_insulation_packages(house, insulator): # args are instances of House and Insulator
return house.roof_area / insulator.area # do the calculation and return it
It might make more sense for the function to be a method of one of the classes. I'd even suggest that Insulator instances might be a good candidates to be instance attributes of the House. That would look something like this:
class House():
def __init__(self, roof_area, roof_insulator, wall_area, wall_insulator):
self.roof_area = roof_area
self.roof_insulator = roof_insulator
self.wall_area = wall_area
self.wall_insulator = wall_insulator
def calculate_roof_insulation_packages(self):
return self.roof_area / self.roof_insulator.area
def calculate_wall_insulation_packages(self, insulator):
return self.wall_area / self.wall_insulator.area
You'd create the house instance with something like this (I'm making up the arguments to the Insulator class, so don't pay too much attention to that part):
good_roof_insulation = Insulator(4, 5) # nonsense args
cheap_wall_insulation = Insulator(5, 12)
my_house = House(100, good_roof_insulation, 87, cheap_wall_insulation)
If you want to use attributes without creating an instance you should use class attributes.
class House(object):
roof_area = 10 # Or whatever you see fit.
roof_surface = 20
class Insulator(object):
thickness = 10 # Or whatever you see fit.
surface = 20
This way you can access the attributes by typing 'House.roof_area' for example.
Although, I don't see why you cannot create an instance. It would prevent harcoding in class attributes and would in your case be much easier.
Also, your operation is not valid syntax, but maybe you just showed pseudo-code. Proper syntax would be:
insulator_packages_needed_for_roof = House.roof_area / Insulator.area
I read multiple article about OOP in python but I didn't find the answer.
here is my sample code as a example :
class Point(object):
"""basic point"""
def __init__(self, x, y):
self.x = x
self.y = y
class Circle(object):
"""basic circle object"""
def __init__(self,center,radius):
self.center = center #should be a point object
self.radius = radius
coord = Point(1, 2)
a = Circle(coord, 4)
b = Circle(4, 5)
If I understand correctly this is valid python code but the circle "b" doesn't have a Point object as the center. if there is a method in the circle object who use the center object to do a calculation (to calculate the circle's area for example) it will fail for the b object. Do I have to enforce type or is it the programmer responsibility to give a expected object type at the instantiation?
As others have said, it is up to you to enforce typing.
However, Python widely uses the concept of duck typing, which means in your case, you don't necessarily need a Point object for the center, you just need something that behaves the same as your Point class. In this simple example, Point doesn't provide any methods; it's simply a class whose objects will have x and y attributes. That means your Circle could accept any object for its center as long as it provides x and y attributes, that is, provides the same interface as Point.
This means that the most important thing to do is document what interface your class provides, and what each function or method expects from its arguments.
It is up to you to enforce types, and up to the caller to provide the proper data.
One of the underlying philosophies of the python community is that we're all responsible programmers. If it is critical that the type is enforced against accidental or malicious mistakes, you must build that into your objects.
The problem we were given is to create a class Segment that represents a line segment in the plane and supports these methods:
__init__(): constructor that takes as input a pair of Point objects that represent the endpoints of the line segment;
length(): returns the length of the segment;
slope() returns the slope of the segment or None if the slope is unbounded.
>>> p1 = Point(3,4)
>>> p2 = Point()
>>> s = Segment (p1, p2)
>>> s.length()
5.0
>>> s.slope()
0.75
I am confused on how I would get it to print the slope as well as the length. I feel like I would know how to do this if I just had to create a function that returned these results, but being able to transform these into classes is what is really confusing me.
If you are new to object-oriented programming, I may throw around a few terms with which you are not familiar: if that's the case, I suggest you look up any words you don't know ;)
The difference between a method and a regular function is the fact that the method is "owned" by the class. A method is basically a function which is only performed on (usually objects of) that class. In python, you declare methods by putting them in the class body, indented once, like so:
class MyClass:
def myMethod(self):
...
One thing to keep in mind is the keyword self - it refers to the instance of that class, i.e. the particular object. You don't pass it as an argument in parentheses, though - it's that s before the . in your example. When you instantiated s by doing s = Segment(p1, p2), you created an instance of the class Segment called s. You must pass self as the first argument to your class methods; how else are you supposed to know upon which object to operate?
__init__() is a special method which defines how to create a new object of that class. You call it by typing the class name, followed by your arguments in parentheses as if the class name were a method. In your example that's Point(3, 4) and Segment(p1, p2).
Normally, you might type s.p1 to get the first point of a Segment, but in your method bodies, you don't know what s is, since the classes are declared before s is instantiated. You do, however, know to pass self, so you would type self.p1 to get the p1 of whichever Segment to which you are referring.
Do you already have the Point class defined somewhere? Look at its code for examples.
If you want some guided exercises, I suggest you check out codeacademy. It's very elementary but it will get the job done.
I need some help in understanding a python concept.
class TilePuzzleProblem(search.Problem):
""" This class is the class for the NxN - blanks tile puzzle problem """
def __init__(self, N, blanks, initial, goal):
""" Initialize """
search.Problem.__init__(self, initial, goal)
self.N = N
self.blanks = blanks
def successor(self, state):
""" Generate the successors of the given state. Returns a list of (move, successor) pairs"""
abstract
def h(self, node):
abstract
Currently the code hangs at the abstract part of the function h(...), but I have no idea what abstract means, hence can not understand what the problem is.
This is a trick described here. There's not keyword abstract in Python, so, if you won't override this method in some subclass, it'll cause NotImplementedError.
An abstract method is one which a class doesn't implement, making it an abstract class; subclasses must override all abstract methods (i.e., provide concrete implementations) to be concrete classes, i.e., ones for which you can make instances. The normal way in Python to express "this method is abstract" is to have the method's body be raise NotImplementedError.
For more about the general concept, apart from its specifics in Python, see wikipedia.
So, formally, you need to subclass this and implement those two methods marked as "abstract". (Depending on your TA's hints, he or she may actually mean that you should replace the word "abstract" with a working body of code, but that would be quite a stretch with respect the normal meaning of "abstract" in OOP!-).
An abstract function is a function with no implementation. It's a placeholder, just there to fill out the class contract so that you know what methods subclass should provide. What you need to do here is create a descendant of TilePuzzleProblem and fill in your own implementation of h. If you want to run it as is, create a descendant and make your h do nothing.
Abstract means the class must be inherited. Abstract or "base" classes are there to provide a base type which you can extend through inheritance. You cannot instantiate an abstract class, only the classes that inherit it.
See this Wikipedia article for more information.
One reason you'd want to use an abstract base class is if you want to categorize or group your sub-types. For example, Car, Truck and Plane would all inherit from the Vehicle abstract base class. You can't just instantiate a "vehicle", you have to instantiate a car, truck or plane. Being abstract protects it from being instantiated.