Here is an example which creates a point as p=Point(x, y)
. Assume that I have some array ppp=(x, y)
where x
and y
are numbers and I want to make it of class Point
but in the way: p=Point(ppp)
. I can do either one or another way but not both simultaneously. Is it possible to have both ways?
Asked
Active
Viewed 479 times
2

tshepang
- 12,111
- 21
- 91
- 136
-
The proposed solution does not work for me. I have: `def __init__(self, x, y = None, z = None): if y is not None and z is not None: self.x, self.y, self.z = x, y, z elif y is not None or z is not None: raise TypeError('Instance may have only 1 or 3 arguments, got 2') else: self.x, self.y, self.z = x` Then I make: `ppp = Point(p)`, where `p = [0.0, 0.0, 0.0]`, and I got: `__new__() takes exactly 4 arguments (2 given)`. It does not matter what are the numbers inside. – Aug 10 '12 at 12:41
-
The solution of Karol Nowak works. – Aug 10 '12 at 12:42
5 Answers
3
There are two different ways to acquire the result, the first is to analyse arguments that you pass to __init__ and in dependence of their quantity and type - choose a decision what are you using to instantiate class.
class Point(object):
x = 0
y = 0
def __init__(self, x, y=None):
if y is None:
self.x, self.y = x, x
else:
self.x, self.y = x, y
The other decision is to use classmethods as instantiators:
class Point(object):
x = 0
y = 0
@classmethod
def from_coords(cls, x, y):
inst = cls()
inst.x = x
inst.y = y
return inst
@classmethod
def from_string(cls, x):
inst = cls()
inst.x, inst.y = x, x
return inst
p1 = Point.from_string('1.2 4.6')
p2 = Point.from_coords(1.2, 4.6)

Rostyslav Dzinko
- 39,424
- 5
- 49
- 62
-
Thank you for your answer. I understand what you mean, and I considered this way. But I did not want to create too many methods, and then call them every time I need to make a Point. The first way is better for me. – Aug 10 '12 at 10:58
-
The second method is much cleaner. Branching to determine type identity just feels wrong. – Sep 20 '12 at 18:47
2
If you know that you have a tuple/list while creating the instance, you can do: p = Point(*ppp)
, where ppp
is the tuple.

Karol Nowak
- 662
- 3
- 8
-
1It should: >>> class Point(object): ... def __init__(self, x, y): ... self.x = x ... self.y = y ... >>> coords = [1, 2] >>> p = Point(*coords) >>> p <__main__.Point object at 0x7ff4a6ec> >>> p.x, p.y (1, 2) – Karol Nowak Aug 10 '12 at 12:08
-
1It means "unpack the list/tuple into multiple arguments". And if you have a `dict` `d`, you can use `**d` to unpack it into keyword arguments. – Karol Nowak Aug 10 '12 at 19:04
-
What is the difference between `init__` and `__init__`? If I use `__init__` the code does not work. – Aug 15 '12 at 09:02
-
@AlexPi: The inital `__` was interpreted as bold markup by the markdown formatting code. The commenter did put them in but did not escape them. `init__` doesn't mean anything. – Martijn Pieters Nov 13 '12 at 11:38
0
class Point:
def __init__(self, x, y=None):
if isinstance(x, tuple):
self.x, self.y = x
else:
self.x = x
self.y = y

Chris Ortner
- 806
- 6
- 11
-
does it work only if the array is tuple? What if I have a list? The second answer is probably better. – Aug 10 '12 at 10:55
0
Yes:
class Point(object):
def __init__(self, x, y=None):
if y is not None:
self.x, self.y = x, y
else:
self.x, self.y = x
def __str__(self):
return "{}, {}".format(self.x, self.y)
print Point(1,2)
# 1, 2
print Point((1,2))
# 1, 2
-1
I would guess that your looking for a way to overload your constructor, as is common in statically typed languages such as C++ and Java.
This is not possible in Python. What you can do is provide different keyword argument combinations, something like:
class Point(object):
def __init__(self, x=None, y=None, r=None, t=None):
if x is not None and y is not None:
self.x = x
self.y = y
elif r is not None and t is not None:
# set cartesian coordinates from polar ones
Which you would then use as:
p1 = Point(x=1, y=2)
p2 = Point(r=1, t=3.14)

Nicola Musatti
- 17,834
- 2
- 46
- 55