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.
Related
First things first, I'm reasonably new to python, but I have been working hard and doing lots of tutorials and sample projects to get better, so, if I'm missing something obvious, I appologize.
I've been trying to figure this out for a while now, and I've done a number of searches here and through the googles, but I can't quite figure out how to turn the examples I've found into what I'm looking for, so I was hoping someone here could give me a push in the right direction.
class Super1:
def __init__(self,artib1,atrib2,atrib3):
self.atrib1 = atrib1
self.atrib2 = atrib2
self.atrib3 = atrib3
class Sub1(Super1):
def __init__(self,atrib4,atrib5,atrib6)
self.atrib4 = atrib4
self.atrib5 = atrib5
self.atrib6 = atrib6
okay, so what I'm having trouble figuring out is, in the tutroials I've done, they said that I could call on the class like this:
spam = Super1("eggs","foo","bar")
and if I input
print spam.atrib1
it would spit out
eggs
What I want to do is make spam = Sub1, but I don't know how to call it so that I can set all the 'attrib's the way I did with Super1.
I looked up a number of 'multiple inheritance' examples, but I can't seem to reconcile the examples into my own needs. Most of the tutorials don't have more than 1 atribute, or often have the sub 'override' the atributes of the super.
I also checked into composition, and I'm not sure that's exactly what I'm looking for for this part of my project, but I do know that I will need it in later parts.
If anyone can point me in the right direction, that would be great.
You need to call the parent class's constructor Super1.__init__(self)
You also need to allow Sub1 to take the arguments for the parent class's constructor.
With the modifications above, your code becomes:
class Sub1(Super1):
def __init__(self, artib1, atrib2, atrib3, atrib4, atrib5, atrib6)
Super1.__init__(self, artib1, atrib2, atrib3)
self.atrib4 = atrib4
self.atrib5 = atrib5
self.atrib6 = atrib6
However, rather than calling the parent class's constructor yourself, you should use the super built-in function:
super(Sub1, self).__init__(artib1, atrib2, atrib3)
That way, you don't have to hard-code the name of the parent class in each sub-classes constructor. This allows you to easily refactor your code. Another added benefit of using super is that will automatically deal with the sticky details of multiple-inheritance problems such as "diamond inheritance".
One more piece of advice is that if you don't know the amount of positional arguments ahead of time that the super class will take, you can use the *args syntax:
class Sub1(Super1):
def __init__(self, atrib4, atrib5, atrib6, *args)
super(Sub1, self).__init__(*args)
self.atrib4 = atrib4
self.atrib5 = atrib5
self.atrib6 = atrib6
If Sub1 inherits from Super1, that's supposed to mean it is a Super1 (with some extra stuff added, or with some customizations). But you can't remove things, so Sub1 must
contain everything a Super1 contains
initialize the Super1 part of itself by calling super(Sub1,self).1.__init__(self, ...) in its own constructor.
So, if you your super class has a member a, whose value is passed to its constructor, your subclass also has (inherits) a member a, and must somehow pass its value to the superclass constructor.
Whether that means
class Sub1(Super1):
def __init__(self, a, b, c, d, e, f):
super(Sub1, self).__init__(a,b,c)
self.d=d
self.e=e
self.f=f
or whether there's some relationship between the super and subclass arguments (or the subclass hard-codes some of the superclass arguments, or ...) depends on your code.
If you call spam = Super1("eggs","foo","bar"). It will call Super class constructor.
The problem is if you want to create a instance for the Sub1 you should spam = Super1("eggs","foo","bar",atrib4,atrib5,atri6). Also you have to change the constructor for the Sub1 as:
def __init__(self,atrib1,atrib2,atrib3,atrib4,atrib5,atrib6):
Super1.__init__(self,atrib1,atrib2,atrib3)
self.atrib4 = atrib4
self.atrib5 = atrib5
self.atrib6 = atrib6`
I have been trying to fully understand this for a while now, and practically speaking I think I understand what happens but I can't seem to find anywhere that confirms wether I understood it correctly:
class test(object):
def __init__(self, this):
self.something = this
example = test("writing")
My question is: In the above example, is it correct that self is simply a stand-in for the instance I am creating? Meaning that when i create an instance and assign it to "example", then "example is put in place of self and behind the scenes does something resembling this:
class test(object):
def __init__(example, this):
example.something = this
example = test("writing")
Furthermore, does that also mean that as long as I am still working with this on a class basis (say in tandem with another class) I should still be using self.something, while I should be using example.something if I am working with it on an instance level?
I hope that made somewhat sense, im still trying to wrap my head properly around all of it, so let me know if I need to try and rephrase it.
For reference sake, should someone else end up asking the same, this reply: Python __init__ and self what do they do? almost did the trick for me, and only really left me a bit in doubt about the above questions.
This is correct. self is the instance of the class (i.e. the object) and you use it inside the class code (inside it's methods).
While the first argument can be named something else (example in your second code), the convention is that we always use self or the code might be highly confusing for other programmers. But you got the gist right by doing that, the example variable in the class (i.e. the self in your first code) and the example variable outside of the class is basically the same thing.
By the way, I'd also avoid the following two things:
having a class name that starts with a small leter case,
using a variable name this (since a variable named this does in some other languages essentially what self does in Python).
In Python, variables do not "contain" objects, they refer to them. So:
class test(object):
def __init__(self, this):
self.something = this
example = test("writing")
In this case example is a reference to the new object, but so is self. It is perfectly legal, and common, to have multiple references to the same object.
If you did:
another = example
this would not create a new object but have another reference to the same object. another, example (and self) would be references to the same single object.
You can test this by looking at the object's unique identifier, using id(). Add:
another = example
print id(another)
print id(example)
you will find that their id's are the same.
I am learning OOP in python and following this and this stackoverflow answers and this post
I understood how class works and how method called and all things but i have some doubts:
Consider this fragment of code:
class Point(object):
def __init__(self,x,y):
self.x = x
self.y = y
def distance(self):
print (self.x)
def bye(self):
print(self.y)
a=Point(1,2)
a.distance()
a.bye()
As i read in tutorial :
when we call a method with some arguments, the corresponding class
function is called by placing the method's object before the first
argument. So, anything like obj.meth(args) becomes Class.meth(obj,
args).
when ObjectA.methodA(arg1, arg2) is called, python internally converts
it for you as:
ClassA.methodA(ObjectA, arg1, arg2)
Now my confusion is why program need to call class with each method ?
Class.meth(obj, args) ??
like when we call a.distance it become Point.distance(a) causes of "self"
when we called a.bye it become Point.bye(a) causes of "self" .
when Point class is necessery with each method if we don't use Point class with each method what will happen?
why can't simply meth(obj, args) works ?
My main doubt is why its called class.some_method with each method when we called with attribute of method . why its needs calls with each one?
#if i am understanding right then its necessary because so that each method can access other methods data like variables and stuff?
The key is
python internally converts it for you
From your standpoint:
meth(self, args) is the syntax you use to define member functions; and
obj.meth(args) is the syntax you use to call member functions.
The meth(obj,args) option is the way procedural languages work. That is often how the implementation works, but expressing the call as obj.meth(args) keeps focus on the object and makes it easier to read which data values (object instances) are being used.
Edit 1 If I understand your question correctly, you are asking why Python needs to know the class when it already has the instance available, and instances know their own types. In fact, Python fetches methods based on the instance all the time. I think the point the tutorial is making is that in Python, the class is the primary place the functions are defined. This is different from some object-oriented languages, in which each instance has its own methods, and they may be completely different from each other. So the tutorial is contrasting the usual approach in Python:
class Foo:
def bar(self):
pass
with an alternative (possible in Python, but not typical):
foo = object() # an empty instance
foo.bar = lambda self: pass
Edit 2 Python methods normally live in the classes, not in the instances. Even if you create 1000 Point objects, there is only one copy of the actual instruction bytes for Point.distance. Those instruction bytes are executed anytime <some point variable>.distance() is called. You are correct that the self parameter is how those instruction bytes know what instance to work on, and how the method can access other data in the passed instance.
Edit 3 self isn't exactly a namespace in the way that local vs. global is. However, it is fair to say that self.foo refers to a foo that is indeed accessible to all the methods of this instance of the current class. Given
a = Point(1,2)
b = Point(3,4)
inside a Point.distance call, self refers to a or b, but not both. So when you call a.distance(), the self.x will be a.x, not b.x. But all methods of Point can access self.x to get whatever the current point's x is.
Edit 4 Suppose you weren't using objects, but instead dictionaries:
a = {'x':1, 'y':2} # make a "point"
b = {'x':3, 'y':4} # make another
def point_distance(point):
print (point['x'])
then you could say:
point_distance(a)
to get the effect of
print (a['x'])
Classes do basically that, with cleaner syntax and some nice benefits. But just as the point parameter to point_distance() refers to one and only one point-like dictionary each time you call point_distance(), the self parameter to Point.distance() refers to one and only one Point instance each time you call <whatever point>.distance().
Because you can have the same method name in different classes, and it needs to call the appropriate one. So if you have
class Class1:
def meth():
print "This is Class 1"
class Class2:
def meth():
print "This is Class 2"
c1 = Class1()
c2 = Class2()
c1.meth() # equivalent to Class1.meth(c1)
c2.meth() # equivalent to Class2.meth(c2)
If it translated c1.meth() to meth(c1), there's no way for the system to know which meth() function to call.
Classes define what is common to all instances of them. Usually this is the code comprising each of its methods. To apply this code to the correct instance object, the language interprets
instance.method(arg1, arg2, ...)
as
class_of_instance.method(instance, arg1, arg2, ...)
so the code is applied to the proper class instance.
Say a meta‑class A expects parameters. A class B of this meta‑class, will have to assign these parameters. Say this class B is to be a base class, and that's its imediat derived classes which are expected to assign these parameters. Is this feasible if this makes sense? If ever this does not make sense, so why?
With the hope it will help to understand the question, here is an extract of the concrete case (which does not pretend to be marvelous), where only the relevant parts are shown (not strictly valid Python, due to place‑holders). Please note this example is valid with Python 3, and I'm not sure it is with the prior Python version (a point I'm adding after a comment).
class Type(type)
def __new__(…, elements)
…
class ArrowType(Type):
def __new__(…, domain, codomain)
# This build a suitable `elements`
# parameter, from its own arguments,
# for the call to `Type.__new__`
…
class Function(
object,
metaclass=ArrowType,
domain=…,
codomain=…)
…
Say the Function class is expected to be a base class, but it's not concrete. It's abstract with regard to its domain and codomain parameters, intended to ArrowType. Say there is no defaults justified, and providing defaults in the vein of None or () or who‑know what, is not considered good (looks like a hack to me).
I tried to make Function abstract, but failed to get a solution from this, as the parameters still needs to be instantiated at the point of Function's definition. Or may be I did it erroneously?
Well, I could use a function:
def function(domain, codomain):
class Function(
object,
metaclass=ArrowType,
domain=domain,
codomain=codomain)
…
return Function
This works, but I don't like it, for multiple reasons: 1) Function is “hidden” in a function body, 2) this is not anymore a single base class (and neither really abstract), as it ends into as many base classes as there are classes derived from it (function being invoked for each), 3) the class‑names the instances gets as displayed by type(…), are ugly.
In few words, what's expected, is to have Function to be abstract, with respect to its domain and codomain parameters, which would be assigned something in its derived only classes.
I am confused with built-in method in Python.
For instance, what is the some_string.lower() and str.lower(some_string) and how are they different?
str is the name of the class of all strings in Python. str.lower is one of its methods.
If you call lower on one of its instances (e.g. 'ABC'.lower()), you call a bound method, which automatically sends the called object as the first argument (usually called self).
If you call lower on the class itself (i.e. you use str.lower()), then you call an unbound method, which doesn't provide the self argument automatically. Therefore, you have to specify the object to act upon by yourself.
If all of this seems hard to understand, it will be easier when you consider how methods are defined in the classes. Let's say we create our own very simple class, which represents a point (X,Y coordinate in space). And has a show() method to print the point.
class Point:
"""This is the constructor of Point"""
def __init__(self, x, y):
# Save arguments as field of our class instance (self)
self.x = x
self.y = y
def show(self):
print self.x, self.y
# We now create an instance of Point:
p = Point(1.0, 2.0)
# We now show p by calling a bound method
p.show()
Note that we didn't have to specify the self argument (so p.show() was called with no arguments). In reality, the previous call was more or less equivalent to this:
Point.show(p)
They're not entirely equivalent, but that's a more advanced topic. One of the simplest cases when they will not be equivalent is if you change the value of p.show after creating the object, for instance:
p.show = 4
Now, p.show() won't even compile, since p.show is not a function anymore, but an integer! However, Point.show(p) would still be unchanged, since we only modified the show attribute in the class instance (p) and not in the class itself (Point).
The first is a bound method call and the second is an unbound method call.
Think about how you'd write a method like this:
class str:
...
def lower(self):
# And so on
The first argument is self. If you use this method from an instance (e.g. some_string.lower(), the instance automatically gets passed as the first argument to the method (as self).
However, if you call it from the class (as an unbound method), e..g str.lower(some_string), there is no instance to automatically pass as the first argument. So, instead, some_string gets passed as self and whatever would've been done with the instance in the first case gets done with some_string.
It's never really necessary to use the unbound version, however, as any string will have a lower() method that you can call. The preferred style is to use some_string.lower().