0

this might be a great pythonic heresy, but I'm looking for syntax that replicates the behavior of the code below, without using both the return and the yield clause in the function "sign" (edit this syntax does not in fact produce the below outputs).

def sign_inner(num):
    return 1 if num>0 else -1 if num<0  else 0

def sign(*nums):
    if len(nums)==1:
        return sign_inner(nums[0])
    for num in nums:
        yield sign_inner(num)

The idea is to output a non-iterable object when a single input is given and an iterable object when multiple inputs are given. Here's an example of how it should behave:

a = sign(3)
a
>>> 1
a, b = sign(3, -5)
a
>>> 1
b
>>> -1

I don't mind constructing a temporary sequence inside the function so long as it is automatically unpacked when returned. Ideally the sign function would look something like this:

def sign(*nums):
    for num in nums:
        yield sign_inner(num)

But yield creates a generator object and in the case of a single input one must add a comma or brackets to unpack it:

a, = sign(3)
a
>>> 1

whereas without the comma:

a = sign(3)
a
>>> <generator object sign at 0x____________>
  • Could you just perhaps always return a list from the `sign` function? – matino Jun 07 '18 at 14:14
  • It is usually not a good practice to mix `return` and `yield` in the same function. https://stackoverflow.com/questions/28806583/is-it-good-practice-to-mix-yield-and-return-statements-in-python – ODiogoSilva Jun 07 '18 at 14:15
  • I have discovered after posting it literally does not work. i suppose the best response would be to adopt Hadi Farah's approach and return a different object depending on the input size. – Amit Weisbord Jun 10 '18 at 10:58
  • @AmitWeisbord: On stackoverflow, [you shouldn't edit answers into the question](https://meta.stackoverflow.com/q/262806/680727). Also, you really shouldn't use a tuple there: tuples are immutable, so each `+=` fully recreates the result tuple, making the time complexity of the function O(n^2) instead of the O(n) you'd get if using a list. Since you probably aren't dealing with huge inputs, it won't matter in practice in this case, but it's a good habit to get to - tuple is just the wrong tool to use here, plain and simple. If you insist on getting a tuple out, just convert it once at the end. – Aleksi Torhamo Jun 10 '18 at 11:40
  • Thank's for the head's up, ill make sure to remove it. – Amit Weisbord Jun 11 '18 at 11:50
  • @AleksiTorhamo i was under the impression list's += has the same functionality so i assumed the tuple object would consume less resources because it is immutable. What would you look for in order to read more about this? – Amit Weisbord Jun 11 '18 at 11:55
  • @AmitWeisbord I don't know a general resource offhand, but the concept is the same as why you should use `res = "".join(items)` instead of `res = ""; for item in items: res += item`. Quick googling gave me [this blog post](http://www.bernardi.cloud/2012/11/06/python-string-concatenation-vs-list-join/), maybe that helps? Also, I forgot to mention it in my original comment, but personally, I'd just rename `sign_internal` to `sign`, and remove the special casing for one item in the other function and rename it `signs`, then call the correct one explicitly as required. – Aleksi Torhamo Jun 11 '18 at 12:18
  • @AmitWeisbord If you happen to use IRC, though, I'm more than happy to explain the concept over IRC in more detail. (I use the nick Alexer on freenode, among other networks) – Aleksi Torhamo Jun 11 '18 at 12:26

1 Answers1

0
def sign_inner(num):
    return 1 if num>0 else -1 if num<0  else 0

def sign(*nums):
    results = []
    for num in nums:
        results.append(sign_inner(num))
    return results[0] if len(results)==1 else results 

A = sign(5,1,-5)
B = sign(5)
a, b, c = sign(5,1,-5)

print(A)
print(B)
print (a)
print (a,b,c)

Output:

>> [1,1,-1]
>> 1
>> 1
>> 1  1  -1
Hadi Farah
  • 1,091
  • 2
  • 9
  • 27
  • 1
    This appears to be the most elegant solution i applied it like this: def sign(*nums): res = tuple() for num in nums: res += (sign_inner(num), ) return res[0] if len(res)==1 else res – Amit Weisbord Jun 07 '18 at 14:50
  • It is a more elegant solution, I'm not very good with tuples but since it works. Good job! – Hadi Farah Jun 07 '18 at 14:52