I a new to object oriented programming. I was trying to create a class that can find distance between two points. I passed points as tuples as coordinates. I wrote this code but its showing error.
class Line:
def __init__(self,coor1,coor2):
self.coor1= coor1
self.coor2= coor2
def distance(self):
print(((self.coor1[0]-self.coor2[0])**2(self.coor1[1]-self.coor2[1])**2)**0.5)
def slope (self):
print((self.coor2[1]-self.coor1[1])/(self.coor2[0]-self.coor1[0]))
coordinate1 = (3,2)
coordinate2 = (8,10)
li = Line(coordinate1,coordinate2)
li.distance()
I know this could be resolved using tuple unpacking but I want to know why my code is not working?
In the function distance you wrote 2(self.coor1[1]-self.coor2[1]) which asks python to execute the __call__ method of an object(2) of class int. You just have to add another addition/subtraction sign after 2.
In the example I'm assuming you want to add.
class Line:
def __init__(self,coor1,coor2):
self.coor1= coor1
self.coor2= coor2
def distance(self):
print(((self.coor1[0]-self.coor2[0])**2+(self.coor1[1]-self.coor2[1])**2)**0.5)
def slope (self):
print((self.coor2[1]-self.coor1[1])/(self.coor2[0]-self.coor1[0]))
coordinate1 = (3,2)
coordinate2 = (8,10)
li = Line(coordinate1,coordinate2)
li.distance()
So I have this dataset of stars that I'm creating a class for (Star). And of those stars some of them are variable stars. I created a child class (Variable), but when I determine one of my Star objects is a variable star (code not included), I want to include extra information to that same object without having to respecify the old information, and further categorize the object into a child class.
I know I can get it to work if I do something like this:
# Class attribute
category = 'variable'
# Initializer / Instance attributes
def __init__(self, name, coordinates, scatter, photometry, periods, amplitudes):
and then:
star1 = Variable('Star 1', ('RA', 'dec'), 0.1, np.sin(np.linspace(0,1,100)), [1,100,1000], [1,2,1])
But I don't want to have to respecify all of that information.
# Parent class
class Star:
# Class attribute
category = 'TESS'
# Initializer / Instance attributes
def __init__(self, name, coordinates, scatter):
self.name = name
self.coordinates = coordinates
self.scatter = scatter
star1 = Star('Star 1', ('RA', 'dec'), 0.1)
print('Parent class')
print('category :', star1.category)
print('name :', star1.name)
print('coordinates :', star1.coordinates)
print('scatter :', star1.scatter, '\n')
# Child class (inherits from Star() class)
class Variable(Star):
# Class attribute
category = 'variable'
# Initializer / Instance attributes
def __init__(self, photometry, periods, amplitudes):
self.photometry = photometry
self.periods = periods
self.amplitudes = amplitudes
star1 = Variable(np.sin(np.linspace(0,1,100)), [1,100,1000], [1,2,1])
print('Child class')
print('category :', star1.category)
print('photometry :', star1.photometry)
print('periods :', star1.periods)
print('amplitudes :', star1.amplitudes)
The code below works as expected. But, if i try:
print(star1.name)
after:
star1 = Variable(np.sin(np.linspace(0,1,100)), [1,100,1000] [1,2,1])
name, coordinates, and scatter seem to be deleted from my object.
You have to call the superclass's initialization method, otherwise it won't ever run! In other words, the Star class's __init__ method doesn't run unless you tell it to.
class Variable(Star):
def __init__(self, arg1, arg2):
super().__init__(arg1)
self.arg2 = arg2
super() is a way of accessing the superclass and its methods. So say you had a merge method in the Star class that merged two stars and you wanted to call it from within the Variable class, you would call super().merge(other_star).
I am trying to create a classmethod which can be called again and again, however it only works once and stops. Here is the code:
class NewBytes(bytes):
def __init__(self, var):
self.var= var
#classmethod
def rip(cls):
return cls(var[2:])
a = b"12asd5789"
x = NewBytes(a)
print(x, x.rip(), x.rip().rip(), x.rip().rip().rip())
Here is what I got from this:
b'12asd5789' b'asd5789' b'asd5789' b'asd5789'
However, what I want to have is:
b'12asd5789' b'asd5789' b'd5789' b'789'
Thanks in advance.
Probably you don't actually want a class method, since you need access to instance state here.
class NewBytes(bytes):
def __init__(self, x):
self.x = x
def rip(self):
return type(self)(self.x[2:])
My previous answer of using self.x doesnt make sense since this is a class method (too quick to answer). I think this is a case of the XY problem, see the below example of how to use a class method.
class Test(object):
x = "hey there whats up this is a long string"
#classmethod
def TestFunction(cls):
cls.x = cls.x[3:]
print(cls.x)
print(Test().x)
Test().TestFunction()
Test().TestFunction()
Test().TestFunction()
Test().TestFunction()
Test().TestFunction()
If I have a class ...
class MyClass:
def method(arg):
print(arg)
... which I use to create an object ...
my_object = MyClass()
... on which I call method("foo") like so ...
>>> my_object.method("foo")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: method() takes exactly 1 positional argument (2 given)
... why does Python tell me I gave it two arguments, when I only gave one?
In Python, this:
my_object.method("foo")
... is syntactic sugar, which the interpreter translates behind the scenes into:
MyClass.method(my_object, "foo")
... which, as you can see, does indeed have two arguments - it's just that the first one is implicit, from the point of view of the caller.
This is because most methods do some work with the object they're called on, so there needs to be some way for that object to be referred to inside the method. By convention, this first argument is called self inside the method definition:
class MyNewClass:
def method(self, arg):
print(self)
print(arg)
If you call method("foo") on an instance of MyNewClass, it works as expected:
>>> my_new_object = MyNewClass()
>>> my_new_object.method("foo")
<__main__.MyNewClass object at 0x29045d0>
foo
Occasionally (but not often), you really don't care about the object that your method is bound to, and in that circumstance, you can decorate the method with the builtin staticmethod() function to say so:
class MyOtherClass:
#staticmethod
def method(arg):
print(arg)
... in which case you don't need to add a self argument to the method definition, and it still works:
>>> my_other_object = MyOtherClass()
>>> my_other_object.method("foo")
foo
In simple words
In Python you should add self as the first parameter to all defined methods in classes:
class MyClass:
def method(self, arg):
print(arg)
Then you can use your method according to your intuition:
>>> my_object = MyClass()
>>> my_object.method("foo")
foo
For a better understanding, you can also read the answers to this question: What is the purpose of self?
Something else to consider when this type of error is encountered:
I was running into this error message and found this post helpful. Turns out in my case I had overridden an __init__() where there was object inheritance.
The inherited example is rather long, so I'll skip to a more simple example that doesn't use inheritance:
class MyBadInitClass:
def ___init__(self, name):
self.name = name
def name_foo(self, arg):
print(self)
print(arg)
print("My name is", self.name)
class MyNewClass:
def new_foo(self, arg):
print(self)
print(arg)
my_new_object = MyNewClass()
my_new_object.new_foo("NewFoo")
my_bad_init_object = MyBadInitClass(name="Test Name")
my_bad_init_object.name_foo("name foo")
Result is:
<__main__.MyNewClass object at 0x033C48D0>
NewFoo
Traceback (most recent call last):
File "C:/Users/Orange/PycharmProjects/Chapter9/bad_init_example.py", line 41, in <module>
my_bad_init_object = MyBadInitClass(name="Test Name")
TypeError: object() takes no parameters
PyCharm didn't catch this typo. Nor did Notepad++ (other editors/IDE's might).
Granted, this is a "takes no parameters" TypeError, it isn't much different than "got two" when expecting one, in terms of object initialization in Python.
Addressing the topic: An overloading initializer will be used if syntactically correct, but if not it will be ignored and the built-in used instead. The object won't expect/handle this and the error is thrown.
In the case of the sytax error: The fix is simple, just edit the custom init statement:
def __init__(self, name):
self.name = name
Newcomer to Python, I had this issue when I was using the Python's ** feature in a wrong way. Trying to call this definition from somewhere:
def create_properties_frame(self, parent, **kwargs):
using a call without a double star was causing the problem:
self.create_properties_frame(frame, kw_gsp)
TypeError: create_properties_frame() takes 2 positional arguments but 3 were given
The solution is to add ** to the argument:
self.create_properties_frame(frame, **kw_gsp)
As mentioned in other answers - when you use an instance method you need to pass self as the first argument - this is the source of the error.
With addition to that,it is important to understand that only instance methods take self as the first argument in order to refer to the instance.
In case the method is Static you don't pass self, but a cls argument instead (or class_).
Please see an example below.
class City:
country = "USA" # This is a class level attribute which will be shared across all instances (and not created PER instance)
def __init__(self, name, location, population):
self.name = name
self.location = location
self.population = population
# This is an instance method which takes self as the first argument to refer to the instance
def print_population(self, some_nice_sentence_prefix):
print(some_nice_sentence_prefix +" In " +self.name + " lives " +self.population + " people!")
# This is a static (class) method which is marked with the #classmethod attribute
# All class methods must take a class argument as first param. The convention is to name is "cls" but class_ is also ok
#classmethod
def change_country(cls, new_country):
cls.country = new_country
Some tests just to make things more clear:
# Populate objects
city1 = City("New York", "East", "18,804,000")
city2 = City("Los Angeles", "West", "10,118,800")
#1) Use the instance method: No need to pass "self" - it is passed as the city1 instance
city1.print_population("Did You Know?") # Prints: Did You Know? In New York lives 18,804,000 people!
#2.A) Use the static method in the object
city2.change_country("Canada")
#2.B) Will be reflected in all objects
print("city1.country=",city1.country) # Prints Canada
print("city2.country=",city2.country) # Prints Canada
It occurs when you don't specify the no of parameters the __init__() or any other method looking for.
For example:
class Dog:
def __init__(self):
print("IN INIT METHOD")
def __unicode__(self,):
print("IN UNICODE METHOD")
def __str__(self):
print("IN STR METHOD")
obj = Dog("JIMMY", 1, 2, 3, "WOOF")
When you run the above programme, it gives you an error like that:
TypeError: __init__() takes 1 positional argument but 6 were given
How we can get rid of this thing?
Just pass the parameters, what __init__() method looking for
class Dog:
def __init__(self, dogname, dob_d, dob_m, dob_y, dogSpeakText):
self.name_of_dog = dogname
self.date_of_birth = dob_d
self.month_of_birth = dob_m
self.year_of_birth = dob_y
self.sound_it_make = dogSpeakText
def __unicode__(self, ):
print("IN UNICODE METHOD")
def __str__(self):
print("IN STR METHOD")
obj = Dog("JIMMY", 1, 2, 3, "WOOF")
print(id(obj))
If you want to call method without creating object, you can change method to static method.
class MyClass:
#staticmethod
def method(arg):
print(arg)
MyClass.method("i am a static method")
I get this error when I'm sleep-deprived, and create a class using def instead of class:
def MyClass():
def __init__(self, x):
self.x = x
a = MyClass(3)
-> TypeError: MyClass() takes 0 positional arguments but 1 was given
You should actually create a class:
class accum:
def __init__(self):
self.acc = 0
def accumulator(self, var2add, end):
if not end:
self.acc+=var2add
return self.acc
In my case, I forgot to add the ()
I was calling the method like this
obj = className.myMethod
But it should be is like this
obj = className.myMethod()
I'm having trouble accessing a superclass variable from a dictionary in the subclass.
The following code is a simplified example:
class SetStuff:
def __init__(self):
self.temperature = 0.0
def set_temp(self, temp):
self.temperature = temp
class DoStuff(SetStuff):
def __init__(self):
super().__init__()
self.info_dict = {"temp": {"current_temp": self.temperature}}
def print_stuff(self):
print("temp_var:", self.temperature)
print("dict:", self.info_dict)
test_stuff = DoStuff()
test_stuff.set_temp(12.1)
test_stuff.print_stuff()
The result of the final call is:
temp_var: 12.1
dict: {'temp': {'current_temp': 0.0}}
Whereas I expected the printed dictionary to contain 12.1. I can't seem to fathom what happens here and how I can fix this.
Any help would be greatly appreciated.
Look at where self.info_dict is set. It's in the __init__ so the value of self.temperature is indeed zero for current_temp because it's being set to the initial value of self.temperature