I'm extracting features from a specific class of objects I have and decided to built a method that extracts all features at once, i.e. call all feature extraction methods and return them in a tuple, as shown below.
def extractFeatures(self):
if self.getLength()<=10:
return ()
else:
return (self.getMean(), # a number
self.getStd(), # a number
self.getSkew(), # a number
self.getKurt(), # a number
# Many other methods here, such as:
self.getACF(), # which returns a TUPLE of numbers...
)
Nevertheless, I have some methods returning tuples with numbers instead of individual numbers, and since I'm still doing some tests and varying the length in each one of these tuples, hard typing self.getACF()[0], self.getACF()[1], self.getACF()[2], ... is not a good idea.
Is there a pythonic way of getting these values already "unpacked" so that I can return a tuple of only numbers instead of numbers and maybe nested tuples of indefinite size?
You could build a list of the values to return, then convert to a tuple at the end. This lets you use append for single values and extend for tuples:
def extractFeatures(self):
if self.getLength() > 10:
out = [self.getMean(), self.getStd(), self.getSkew()]
out.append(self.getKurt()] # single value
out.extend(self.getACF()) # multiple values
return tuple(out)
Note that this will implicitly return None if self.getLength() is 10 or less.
However, bear in mind that your calling function now needs to know exactly what numbers are coming and in what order. An alternative in this case is to return a dictionary:
return {'mean': self.getMean(), ... 'ACF': self.getACF()}
Now the calling function can easily access the features required by key, and you can pass these as keyword arguments to other functions with dictionary unpacking:
def func_uses_mean_and_std(mean=None, std=None, **kwargs):
...
features = instance.extractFeatures()
result = func_uses_mean_and_std(**features)
Related
I am making a function that would get data from API queries and I need to have a dynamic indexing regardless if it is a list of dictionaries, dictionaries inside of a dictionary and so on.
Is it possible to create a function that would return the value of a nested dictionary or nested list with a Dynamic Index? I have tried one but it uses exec() which I think is not a good idea.
For example I have multiple lists and dictionaries.
Set1={"A":{"a":1,"b":2}}
Set2=[1,2,3]
Set3=[{"C":3},{"D":2}]
And I would need to index all of the Sets that have a value of "2."
Would it be possible to create something like
Function["A"]["b"]
Function[1]
Function[1]["D"]
Since all of them would just return 2?
It is not strictly necessary to use the index/key access notation. You could write a function along the following lines:
def accessor(data, *bits):
for bit in bits:
try:
data = data[bit]
except (TypeError, KeyError, IndexError):
raise
# or handle differently
return data
>>> accessor(Set1, "A", "b")
2
>>> accessor(Set2, 1)
2
>>> accessor(Set3, 1, "D")
2
Note that if you receive the bits dynamically, e.g. as a list, you can unpack them like:
# e.g. bits = ["A", "b"]
accessor(Set1, *bits)
I need to find a way to split a string of multiples numbers into multiples strings of those numbers and then split again to have individual digits which would allow me to test those first inputed numbers to see if they are a harshad number without using for, else, while and if.
So far i'm able to split the input string:
a = input("Multiple numbers separated by a ,: ")
a.split(",")
Then I need to split again I think I need to use the map function. Any idea how to go any further.
The python builtin functions map, filter, and reduce are going to be your friend when you are working in a more functional style.
map
The map function lets you transform each item in an iterable (list, tuple, etc.) by passing it to a function and using the return value as a new value in a new iteratable*.
The non-functional approach would use a for ... in construct:
numbers_as_strings = ["1", "12", "13"]
numbers_as_ints = []
for number in numbers_as_strings:
numbers_as_ints.append(int(number))
or more concisely a list comprehension
numbers_as_ints =[int(number) for number in numbers_as_strings]
Since you are eschewing for there is another way
numbers_as_ints = map(int, numbers_as_strings)
But you don't just want your strings mapped to integers, you want to test them for harshadiness. Since we're doing the functional thing let's create a function to do this for us.
def is_harshad(number_as_string):
return # do your harshad test here
Then you can map your numbers through this function
list(map(is_harshad, numbers_as_string)) # wrap in list() to resolve the returned map object.
>>> [True, True, False]
But maybe you want the results as a sequence of harshady number strings? Well check out filter
filter
The filter function lets you choose which items from an iterable you want to keep in a new iterable. You give it a function that operates on an single item and returns True for a keeper or False for a rejection. You also give it an iterable of items to test.
A non-functional way to do this is with a for loop
harshady_numbers = []
for number in numbers_as_strings:
if is_harshad(number):
harshady_numbers.append(number)
Or more concisely and nicely, with a list comprehension
harshady_numbers = [number for number in numbers_as_strings if is_harshady(number)]
But, since we're getting functional well use filter
harshady_numbers = filter(is_harshady, numbers_as_strings)
That's about it. Apply the same functional thinking to complete the is_harshad function and you're done.
map() can take more than one iterable argument and it returns an iterator not a list.
I have first function which is not possible to modify or change! It displays value of the variable (main_index field which cannot be the list, tuple, dictionary etc. It is simple just a variable and must remain as it is)
That function triggers second function which can return multiple values so the idea is to somehow display those multiple values one by one, but not putting them into the list or dict. etc. Second function can be changed in any way.
Code is the following (please take into account that first function cannot be modified in any way, I am just simplifying it here).
def not_changeable():
value_to_check='7.1'
main_index=generate_index(value_to_check)
print (main_index)
def generate_index(index):
dictionary={'7.1.1':{'value':'1'},'7.1.2':{'value':'2'},'7.100.3':{'value':'3'}}
filtered_dict={}
concatanatedIndex=index+'.'
for k in dictionary.keys():
if concatanatedIndex in k:
filtered_dict[k]=dictionary[k]
print (filtered_dict)
for indx in filtered_dict:
return (filtered_dict.get(indx).get('value'))
not_changeable()
As output I am getting one value (because of return function which ends the script)
{'7.1.1': {'value': '1'}, '7.1.2': {'value': '2'}}
1
But I would like to get values
1
2
without any modification on the first function.
I am aware that if I return list I will be able to display all values, but is it possible to display 1 and 2 without modifications on the first function?
Returning in a for loop is often not what you want, it might be better to build the data structure in the loop and then return later, or return the whole data structure as it is being built in a comprehension. Here you can return a string with newline characters instead of a value, like this:
def generate_index(index):
dictionary={'7.1.1':{'value':'1'},'7.1.2':{'value':'2'},'7.100.3':{'value':'3'}}
filtered_dict={}
concatanatedIndex=index+'.'
for k in dictionary.keys():
if concatanatedIndex in k:
filtered_dict[k]=dictionary[k]
print (filtered_dict)
return '\n'.join(sorted(filtered_dict.get(indx).get('value') for indx in filtered_dict))
This will print
{'7.1.2': {'value': '2'}, '7.1.1': {'value': '1'}}
1
2
Breakdown of the last statement: '\n'.join(sorted(filtered_dict.get(indx).get('value') for indx in filtered_dict)):
We use a comprehension to generate the data we are interested in: filtered_dict.get(indx).get('value') for indx in filtered_dict - this is actually a generator comprehension, but you can put [] to make it a list comprehension.
Because we are iterating over a dictionary, and dictionaries not guaranteed to be in a certain order (though I believe this is changed with Python 3.6), I have added the sorted call to make sure 1 comes before 2.
To turn an iterable (like a list) into a string, we can use the string method .join(), which creates a string by joining together the elements in the list and puts the string in between each one. so '-hello-'.join(['a', 'b', 'c']) will become 'a-hello-b-hello-c'.
Actually a simpler way to build the return string would be to iterate over dict.values() instead of the actual dict. And if we are using python version > 3.6 we can skip the sorted call, so the return simply becomes: return '\n'.join(v.get('value') for v in filtered_dict.values()).
But a better design might be to return the values in a dictionary and print them in a specific format in a separate function that is only responsible for display.
You can adapt the generate_index function to return a generator, aka something you can iterate over (note the last line in the code below).
You can read up on generators here or see the documentation
dictionary={'7.1.1':{'value':'1'},'7.1.2':{'value':'2'},'7.100.3':{'value':'3'}}
filtered_dict={}
concatanatedIndex=index+'.'
for k in dictionary.keys():
if concatanatedIndex in k:
filtered_dict[k]=dictionary[k]
print (filtered_dict)
for indx in filtered_dict:
# change from return to yield here to create a generator
yield filtered_dict.get(indx).get('value')
Note that by calling this generate_index, you were already kind of shooting for a generator! Then you can call the result in your other function like so:
main_index=generate_index(value_to_check)
for index in main_index:
print(index)
Hope this does what you want
Here is the question, I'm trying to define a function sample_mean that takes in a list of numbers as a parameter and returns the sample mean of the the numbers in that list. Here is what I have so far, but I'm not sure it is totally right.
def sample_mean(list):
""" (list) -> number
takes in a list of numbers as a parameter and returns the sample mean of the the numbers in that list
sample_mean =
sample_mean =
"""
mean = 0
values = [list]
for list in values:
print('The sample mean of', values, 'is', mean(list))
Firstly, don't use list as a name because it shadows/hides the builtin list class for the scope in which it is declared. Use a name that describes the values in the list, in this case samples might be a good name. The function could be implemented with something like this:
def sample_mean(samples):
total = 0
for value in samples:
total = total + value
return total / float(len(samples))
Or a shorter version which avoids writing your own loop by making use of Python's sum() function :
def sample_mean(samples):
return sum(samples) / float(len(samples))
Call the function like this:
>>> print(sample_mean([1,2,3,4,5]))
3.0
Note the use of float() to ensure that the division operation does not lose the fractional part. This is only an issue in Python 2 which uses integer division by default. Alternatively you could add this to the top of your script:
from __future__ import division
If you are sure that you only need to support Python 3 you can remove the float() and ignore the above.
As stated above by #idjaw, don't use list as a parameter instead use listr (for example). Your values = [list] is erroneous (also stated by #idjaw) and should be removed.
Also, according to PEP257, you should not use "(list) -> number" in your docstrings as that should only be used for builtins.
Finally, your loop should look like for l in listr: and then you add values to your mean variable. divide it by the number of values in the list and print the result.
I have a class that stores a list of lists in a matrix style, and it can just be indexed like [x,y].
Right now I have these set:
test_dict = {1:"cow",2:"horse"}
randommap = mapArray(None, (20,20))
random map is just filled with lists of 1s. So any index will return a 1. But here is where I get lost, maybe because of a misunderstanding about how dictionaries work:
test_dict[1]
That obviously gives back "cow"
and
randommap[1,1] #or any two x,y values up to 20 for that matter
gives me a value of 1.
But how come this gives me a key error:
test_dict[randommap[1,1]]
In isolation, indexing randommap there gives me a value of 1, so shouldn't that 1 be supplied as an index for test_dict, thus returning me "cow"?
Update:
These are the two methods I presume are causing the issue. It appears that they are returning strings instead of integers, but I don't know If I quite understand the difference between the two.
def __str__(self):
return str(self.mapdata)
def __repr__(self):
return str(self.mapdata)
Here is the overloaded __getitem__ method:
def __getitem__(self, (x,y)):
#Just reverses it so it works intuitively and the array is
# indexed simply like map[x,y] instead of map[y][x]
return mapArray(self.mapdata[y][x])
Sorry the formatting seems to have been messed up a bit.
There is a difference between 1 (and integer), "1" (a string), and any custom class whose __repr__() method returns the string "1" when called. They will all be printed as 1 in the console, but are not equivalent for dict look-ups.
You need to check that type(randommap[1, 1]) is indeed an int.
Update: Your __getitem__ method doesn't return integers, it returns a new instance of your mapArray class. Did you mean to return just the values themselves? E.g.:
def __getitem__(self, (x,y)):
#Just reverses it so it works intuitively and the array is
# indexed simply like map[x,y] instead of map[y][x]
return self.mapdata[y][x]
Given the updated question, it seems that __getitem__ returns a new mapArray.
I think your overloaded __getitem__ should be something like
def __getitem__(self, (x,y)):
return self.mapdata[y][x]
instead, (assuming that the [y][x] order is intentional).