Is there a builtin way to define a function that takes either 1 argument or 3?
There's this error in Python when calling builtin type()
with no arguments:
TypeError: type() takes 1 or 3 arguments
How can we define such a method?
Is there a builtin way? Or we need to do something like this:
>>> def one_or_three(*args):
... if len(args) not in [1,3]:
... raise TypeError("one_or_three() takes 1 or 3 arguments")
...
>>> one_or_three(1)
>>> one_or_three()
TypeError: one_or_three() takes 1 or 3 arguments
>>> one_or_three(1,2)
TypeError: one_or_three() takes 1 or 3 arguments
python function
add a comment |
There's this error in Python when calling builtin type()
with no arguments:
TypeError: type() takes 1 or 3 arguments
How can we define such a method?
Is there a builtin way? Or we need to do something like this:
>>> def one_or_three(*args):
... if len(args) not in [1,3]:
... raise TypeError("one_or_three() takes 1 or 3 arguments")
...
>>> one_or_three(1)
>>> one_or_three()
TypeError: one_or_three() takes 1 or 3 arguments
>>> one_or_three(1,2)
TypeError: one_or_three() takes 1 or 3 arguments
python function
5
I can't think of an in-built way.. a couple of alternatives are using a decorator or anassert
.
– jpp
Nov 12 '18 at 12:06
1
This specific error is hardcoded intypeobject.c
in the functiontype_new
. It returns a valid result fornargs == 1
and then throws an error forif (nargs != 3)
. Alas, peeking at the source doesn't readily tell if it can be done in native Python.
– usr2564301
Nov 12 '18 at 12:47
add a comment |
There's this error in Python when calling builtin type()
with no arguments:
TypeError: type() takes 1 or 3 arguments
How can we define such a method?
Is there a builtin way? Or we need to do something like this:
>>> def one_or_three(*args):
... if len(args) not in [1,3]:
... raise TypeError("one_or_three() takes 1 or 3 arguments")
...
>>> one_or_three(1)
>>> one_or_three()
TypeError: one_or_three() takes 1 or 3 arguments
>>> one_or_three(1,2)
TypeError: one_or_three() takes 1 or 3 arguments
python function
There's this error in Python when calling builtin type()
with no arguments:
TypeError: type() takes 1 or 3 arguments
How can we define such a method?
Is there a builtin way? Or we need to do something like this:
>>> def one_or_three(*args):
... if len(args) not in [1,3]:
... raise TypeError("one_or_three() takes 1 or 3 arguments")
...
>>> one_or_three(1)
>>> one_or_three()
TypeError: one_or_three() takes 1 or 3 arguments
>>> one_or_three(1,2)
TypeError: one_or_three() takes 1 or 3 arguments
python function
python function
asked Nov 12 '18 at 12:03
AdelinAdelin
4,65531542
4,65531542
5
I can't think of an in-built way.. a couple of alternatives are using a decorator or anassert
.
– jpp
Nov 12 '18 at 12:06
1
This specific error is hardcoded intypeobject.c
in the functiontype_new
. It returns a valid result fornargs == 1
and then throws an error forif (nargs != 3)
. Alas, peeking at the source doesn't readily tell if it can be done in native Python.
– usr2564301
Nov 12 '18 at 12:47
add a comment |
5
I can't think of an in-built way.. a couple of alternatives are using a decorator or anassert
.
– jpp
Nov 12 '18 at 12:06
1
This specific error is hardcoded intypeobject.c
in the functiontype_new
. It returns a valid result fornargs == 1
and then throws an error forif (nargs != 3)
. Alas, peeking at the source doesn't readily tell if it can be done in native Python.
– usr2564301
Nov 12 '18 at 12:47
5
5
I can't think of an in-built way.. a couple of alternatives are using a decorator or an
assert
.– jpp
Nov 12 '18 at 12:06
I can't think of an in-built way.. a couple of alternatives are using a decorator or an
assert
.– jpp
Nov 12 '18 at 12:06
1
1
This specific error is hardcoded in
typeobject.c
in the function type_new
. It returns a valid result for nargs == 1
and then throws an error for if (nargs != 3)
. Alas, peeking at the source doesn't readily tell if it can be done in native Python.– usr2564301
Nov 12 '18 at 12:47
This specific error is hardcoded in
typeobject.c
in the function type_new
. It returns a valid result for nargs == 1
and then throws an error for if (nargs != 3)
. Alas, peeking at the source doesn't readily tell if it can be done in native Python.– usr2564301
Nov 12 '18 at 12:47
add a comment |
2 Answers
2
active
oldest
votes
First, type is not native Python (at least in CPython), but C.
The inspect
module can confirm it easily (even if documented as a builtin function, type
is implemented as a class in CPython):
>>> print(inspect.signature(type.__init__))
(self, /, *args, **kwargs)
>>> print(sig.parameters['self'].kind)
POSITIONAL_ONLY
The parameter kind is POSITIONAL_ONLY
, which cannot be created in Python.
That means that it will not be possible to reproduce exactly the behaviour of type.
Python source allows only 2 signatures for variable number of arguments:
3 parameters, 2 of them being optional:
type(object_or_name, bases = None, dict = None)
This would be very different, because it will accept gladly
type(obj, None)
which is definitely not what is expected herea simple
*args
parameter whose length will be tested by hand - your proposal. This will be much closer to nativetype
behaviour, because it really requires 1 or 3 parameters, whatever the values.
TL/DR: the answer to your question is that we really need the something like that way.
add a comment |
This behavior is perfectly possible in Python.
def one_or_three(one, two=object(), three=object()):
two_sentinel, three_sentinel = one_or_three.__defaults__
if (two == two_sentinel) != (three == three_sentinel):
raise TypeError("one_or_three() takes 1 or 3 arguments")
...
This has the benefits of named arguments (semantic value, passing in by name, etc) but is basically a variation on checking the values of some variables to know whether one or three things were passed.
Note that the two calls to object()
produce two different objects and bind them to the function:
>>> one_or_three.__defaults__
(<object object at 0x00168540>, <object object at 0x00168ED0>)
This way, they are globally unique. If you instead used None
as your sentinel object, then it wouldn't be possible to pass in None
as an argument (though of course that may be desired).
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53261804%2fis-there-a-builtin-way-to-define-a-function-that-takes-either-1-argument-or-3%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
First, type is not native Python (at least in CPython), but C.
The inspect
module can confirm it easily (even if documented as a builtin function, type
is implemented as a class in CPython):
>>> print(inspect.signature(type.__init__))
(self, /, *args, **kwargs)
>>> print(sig.parameters['self'].kind)
POSITIONAL_ONLY
The parameter kind is POSITIONAL_ONLY
, which cannot be created in Python.
That means that it will not be possible to reproduce exactly the behaviour of type.
Python source allows only 2 signatures for variable number of arguments:
3 parameters, 2 of them being optional:
type(object_or_name, bases = None, dict = None)
This would be very different, because it will accept gladly
type(obj, None)
which is definitely not what is expected herea simple
*args
parameter whose length will be tested by hand - your proposal. This will be much closer to nativetype
behaviour, because it really requires 1 or 3 parameters, whatever the values.
TL/DR: the answer to your question is that we really need the something like that way.
add a comment |
First, type is not native Python (at least in CPython), but C.
The inspect
module can confirm it easily (even if documented as a builtin function, type
is implemented as a class in CPython):
>>> print(inspect.signature(type.__init__))
(self, /, *args, **kwargs)
>>> print(sig.parameters['self'].kind)
POSITIONAL_ONLY
The parameter kind is POSITIONAL_ONLY
, which cannot be created in Python.
That means that it will not be possible to reproduce exactly the behaviour of type.
Python source allows only 2 signatures for variable number of arguments:
3 parameters, 2 of them being optional:
type(object_or_name, bases = None, dict = None)
This would be very different, because it will accept gladly
type(obj, None)
which is definitely not what is expected herea simple
*args
parameter whose length will be tested by hand - your proposal. This will be much closer to nativetype
behaviour, because it really requires 1 or 3 parameters, whatever the values.
TL/DR: the answer to your question is that we really need the something like that way.
add a comment |
First, type is not native Python (at least in CPython), but C.
The inspect
module can confirm it easily (even if documented as a builtin function, type
is implemented as a class in CPython):
>>> print(inspect.signature(type.__init__))
(self, /, *args, **kwargs)
>>> print(sig.parameters['self'].kind)
POSITIONAL_ONLY
The parameter kind is POSITIONAL_ONLY
, which cannot be created in Python.
That means that it will not be possible to reproduce exactly the behaviour of type.
Python source allows only 2 signatures for variable number of arguments:
3 parameters, 2 of them being optional:
type(object_or_name, bases = None, dict = None)
This would be very different, because it will accept gladly
type(obj, None)
which is definitely not what is expected herea simple
*args
parameter whose length will be tested by hand - your proposal. This will be much closer to nativetype
behaviour, because it really requires 1 or 3 parameters, whatever the values.
TL/DR: the answer to your question is that we really need the something like that way.
First, type is not native Python (at least in CPython), but C.
The inspect
module can confirm it easily (even if documented as a builtin function, type
is implemented as a class in CPython):
>>> print(inspect.signature(type.__init__))
(self, /, *args, **kwargs)
>>> print(sig.parameters['self'].kind)
POSITIONAL_ONLY
The parameter kind is POSITIONAL_ONLY
, which cannot be created in Python.
That means that it will not be possible to reproduce exactly the behaviour of type.
Python source allows only 2 signatures for variable number of arguments:
3 parameters, 2 of them being optional:
type(object_or_name, bases = None, dict = None)
This would be very different, because it will accept gladly
type(obj, None)
which is definitely not what is expected herea simple
*args
parameter whose length will be tested by hand - your proposal. This will be much closer to nativetype
behaviour, because it really requires 1 or 3 parameters, whatever the values.
TL/DR: the answer to your question is that we really need the something like that way.
answered Nov 12 '18 at 13:17
Serge BallestaSerge Ballesta
76.5k956130
76.5k956130
add a comment |
add a comment |
This behavior is perfectly possible in Python.
def one_or_three(one, two=object(), three=object()):
two_sentinel, three_sentinel = one_or_three.__defaults__
if (two == two_sentinel) != (three == three_sentinel):
raise TypeError("one_or_three() takes 1 or 3 arguments")
...
This has the benefits of named arguments (semantic value, passing in by name, etc) but is basically a variation on checking the values of some variables to know whether one or three things were passed.
Note that the two calls to object()
produce two different objects and bind them to the function:
>>> one_or_three.__defaults__
(<object object at 0x00168540>, <object object at 0x00168ED0>)
This way, they are globally unique. If you instead used None
as your sentinel object, then it wouldn't be possible to pass in None
as an argument (though of course that may be desired).
add a comment |
This behavior is perfectly possible in Python.
def one_or_three(one, two=object(), three=object()):
two_sentinel, three_sentinel = one_or_three.__defaults__
if (two == two_sentinel) != (three == three_sentinel):
raise TypeError("one_or_three() takes 1 or 3 arguments")
...
This has the benefits of named arguments (semantic value, passing in by name, etc) but is basically a variation on checking the values of some variables to know whether one or three things were passed.
Note that the two calls to object()
produce two different objects and bind them to the function:
>>> one_or_three.__defaults__
(<object object at 0x00168540>, <object object at 0x00168ED0>)
This way, they are globally unique. If you instead used None
as your sentinel object, then it wouldn't be possible to pass in None
as an argument (though of course that may be desired).
add a comment |
This behavior is perfectly possible in Python.
def one_or_three(one, two=object(), three=object()):
two_sentinel, three_sentinel = one_or_three.__defaults__
if (two == two_sentinel) != (three == three_sentinel):
raise TypeError("one_or_three() takes 1 or 3 arguments")
...
This has the benefits of named arguments (semantic value, passing in by name, etc) but is basically a variation on checking the values of some variables to know whether one or three things were passed.
Note that the two calls to object()
produce two different objects and bind them to the function:
>>> one_or_three.__defaults__
(<object object at 0x00168540>, <object object at 0x00168ED0>)
This way, they are globally unique. If you instead used None
as your sentinel object, then it wouldn't be possible to pass in None
as an argument (though of course that may be desired).
This behavior is perfectly possible in Python.
def one_or_three(one, two=object(), three=object()):
two_sentinel, three_sentinel = one_or_three.__defaults__
if (two == two_sentinel) != (three == three_sentinel):
raise TypeError("one_or_three() takes 1 or 3 arguments")
...
This has the benefits of named arguments (semantic value, passing in by name, etc) but is basically a variation on checking the values of some variables to know whether one or three things were passed.
Note that the two calls to object()
produce two different objects and bind them to the function:
>>> one_or_three.__defaults__
(<object object at 0x00168540>, <object object at 0x00168ED0>)
This way, they are globally unique. If you instead used None
as your sentinel object, then it wouldn't be possible to pass in None
as an argument (though of course that may be desired).
answered Nov 21 '18 at 12:25
Joel HarmonJoel Harmon
1212
1212
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53261804%2fis-there-a-builtin-way-to-define-a-function-that-takes-either-1-argument-or-3%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
5
I can't think of an in-built way.. a couple of alternatives are using a decorator or an
assert
.– jpp
Nov 12 '18 at 12:06
1
This specific error is hardcoded in
typeobject.c
in the functiontype_new
. It returns a valid result fornargs == 1
and then throws an error forif (nargs != 3)
. Alas, peeking at the source doesn't readily tell if it can be done in native Python.– usr2564301
Nov 12 '18 at 12:47