How to do something like this in python
def func1():
x = 2
y = 3
return x, y
def funcx():
print(func1().x)
def funcy():
print(func1().y)
So basically return multiple values from a single function then use each returned value in a different function
Python functions can return only one value, but it is easy for that value to contain others. In your example, func1 returns a single tuple, which in turn contains two values.
>>> def func1():
... x = 2
... y = 3
... return x, y
...
>>> func1()
(2, 3)
You can index or unpack this return value just like any other tuple:
>>> func1()[0]
2
>>> func1()[1]
3
>>> a, b = func1()
>>> a
2
You can use indexing also in your desired functions:
def funcx():
print(func1()[0])
def funcy():
print(func1()[1])
If you desire named fields, you can use a dict or namedtuple:
# dict
def func1():
return {'x': 2, 'y': 3}
def funcx():
print(func1()['x'])
# namedtuple
from collections import namedtuple
Point2D = namedtuple('Point2D', ['x', 'y'])
def func1():
return Point2D(x=2, y=3)
def funcx():
print(func1().x)
Related
Hi Stackoverflow geeks,
I have this list:
[(('Male', 'White'), 6488)]
& I want to convert it to a tuple like this:
('Male', 'White', 6488)
I appreciate if you help me with the code.
This is a generalised solution to flatten lists that contain a possible combination of iterables and non-iterables of various types:
import functools
from typing import Any, Iterable, List
def ext(x: List, y: Any) -> List:
"""
Returns x, extended or appended to include the individual constituents of y.
x is always a list. y may or may not be.
"""
# Because strings are iterable, we don't want them to be broken down
# into individual characters - so we check that y is iterable but not a
# string.
if isinstance(y, Iterable) and not isinstance(y, str):
x.extend(y)
else:
x.append(y)
return x
Use the above function with functools.reduce to work your way through the original iterable, accumulating its contents into a single list.
You provide [] as an initial value for x passed into ext, to guarantee that it is always a list for the purposes of ext. Once you have that list, convert it into a tuple to give you your desired result.
Trying this on your original problem - arr1 below, you need to run this approach twice, because your original iterable only contains one iterable of its own:
arr1 = [('Male', 'White'), 6488]
result1 = tuple(functools.reduce(ext, arr1, []))
print (result1)
# Result -> (('Male', 'White'), 6488)
result1 = tuple(functools.reduce(ext, result1, []))
print(result1)
# Result -> ('Male', 'White', 6488)
Trying it on a more complex object:
arr2 = [('foo'), 'bar', ['bleep', 'bloop'], {'a': 1, 'b': 2}]
result2 = tuple(functools.reduce(ext, arr2, []))
print(result2)
# Result -> ('foo', 'bar', 'bleep', 'bloop', 'a', 'b')
Note that with dictionaries, you only get the keys back. If you want key/value pairs, you'll need to add a specific guard for this, like so:
def ext2(x: List, y: Any) -> List:
"""
Reworking ext to deal differently with dictionaries in the original iterable.
"""
if isinstance(y, Iterable) and not isinstance(y, str):
if isinstance(y, dict):
x.extend(y.items())
else:
x.extend(y)
else:
x.append(y)
return x
Trying it again on the last example::
arr2 = [('foo'), 'bar', ['bleep', 'bloop'], {'a': 1, 'b': 2}]
result3 = tuple(functools.reduce(ext2, arr2, []))
print(result3)
# Result -> ('foo', 'bar', 'bleep', 'bloop', ('a', 1), ('b', 2))
Imagine having 200 functions, which represent 200 ways to solve a problem or calculate something like
def A():
...
def B():
...
.
.
.
and the method will be chosen as an input argument, meaning the user decides which method to use, giving this as an argument while running the program like "A" for function/method A.
how to chose that function without if-checking the name of every single function in python.
You can use a dictionary to access directly the function that you need in O(1) complexity. For example:
def A(x):
pass
def B(x):
pass
func_map = {"A": A, "B": B}
Say that you store the user input in a variable chosen_func, then to select and run the right function, do the following:
func_map[chosen_func](x)
Example:
In [1]: def A(x):
...: return x + x
In [2]: def B(x):
...: return x * x
In [3]: func_map = {"A": A, "B": B}
In [4]: func_map["A"](10)
Out[4]: 20
In [5]: func_map["B"](10)
Out[5]: 100
If I use my_set.update(my_list) where some elements of my_list are == existing elements in my_set, does it replace the existing items or not?
It does not replace existing elements, as can be seen from the following example:
>>> s = {1}
>>> s.add(1.0)
>>> s
{1}
The same behavior holds for dictionary keys:
>>> d = {1: 'foo'}
>>> d.update({1.0: 'bar'})
>>> d
{1: 'bar'}
It doesn't:
from dataclasses import dataclass
#dataclass(frozen=True)
class MyType:
hashed: int # This will contribute to hash equality
not_hashed: str # This won't contribute to hash equality
# Override hashing/equality
def __eq__(self, other):
return hash(self) == hash(other)
def __hash__(self):
return hash((self.hashed, ))
x = { MyType(hashed=1, not_hashed="original") } # Add an item to a set
x.update([MyType(1, "new")]) # .update() with a different item with the same hash
print(x)
# { MyType(hashed=1, not_hashed='original') } # The original item is in the set
When I run this code it returns that the numpy.ndarray object has no attributes. I'm trying to write a function that in case the number given is in the array will return with the position of that number in the array.
a = np.c_[np.array([1, 2, 3, 4, 5])]
x = int(input('Type a number'))
def findelement(x, a):
if x in a:
print (a.index(x))
else:
print (-1)
print(findelement(x, a))
Please use np.where instead of list.index.
import numpy as np
a = np.c_[np.array([1, 2, 3, 4, 5])]
x = int(input('Type a number: '))
def findelement(x, a):
if x in a:
print(np.where(a == x)[0][0])
else:
print(-1)
print(findelement(x, a))
Result:
Type a number: 3
2
None
Note np.where returns the indices of elements in an input array where
the given condition is satisfied.
You should check out np.where and np.argwhere.
Trying to figure best way to union of two dictionaries. Here is the code that I have. Counter is one of the options that I found.
def __add__(self,right):
mergedbag = Bag()
mergedbag.bag_value = copy.copy(self.bag_value)
for item in right.bag_value.keys():
mergedbag.bag_value[item] += right.bag_value[item]
return mergedbag
To test if two dictionaries have the same contents, simply use an equality test:
self.bag_items == bag_equal.bag_items
Python does this comparison test efficiently; keys and values have to match exactly and difference in length means the dictionaries are not equal:
>>> a = {'a': 'b'}
>>> b = {'a': 'b'}
>>> a == b
True
>>> b['b'] = 'c'
>>> a == b
False
>>> del b['b']
>>> b['a'] = 'c'
>>> a == b
False
>>> b['a'] = 'b'
>>> a == b
True
Note that rather than raise a TypeError, __eq__ should return the NotImplemented sentinel object to signal that equality testing is not supported:
def __eq__(self, other):
if not isinstance(other, Bag):
return NotImplemented
return self.bag_items == other.bag_items
As a side-note, the in membership operator already returns either True or False, there is no need to use a conditional expression in __contains__; the following is enough:
def __contains__(self, include):
return include in self.bag_items
Your code never actually does anything with the items passed in however, nor are you ever counting the items. Your count() method should just look up the element in self.bag_items and return the count once you properly track counts.