Understanding Python help() 's ... syntax, and the pop function for dictionaries - python

The ... next to various python "help" method/function descriptions don't seem to be defined anywhere. What does function(...) mean, in the context of the python help output description?
Specifically, how should the documentation for python's pop function be interpreted?
Details
Given that the pop requires an input, it is a little confusing that help({}) doesn't show this in the functions input description (...).
Interpreting the ... as "ditto" doesn't work - for example, "items" cannot take any inputs.
To be clear, this is the functions input definition from help.
pop(...)
The full output of the help({}) function, for get...pop is below. What do the ...'s mean, and, why is there no input defined, for the pop function?
| get(self, key, default=None, /)
| Return the value for key if key is in the dictionary, else default.
|
| items(...)
| D.items() -> a set-like object providing a view on D's items
|
| keys(...)
| D.keys() -> a set-like object providing a view on D's keys
|
| pop(...)
| D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
| If key is not found, d is returned if given, otherwise KeyError is raised

languages = ['Python', 'Java', 'C++', 'Ruby', 'C']
# here is a list
languages.pop(2)
# this will call the pop function for
# languages list and the it removes the element
# at the specified position.
# so after you take a look at languages
languages
Output: ['Python', 'Java', 'Ruby', 'C']
So as for your question. "pop" is a function so its usage is like any other function
thelist.pop(the-element-you-want-to-be-removed)

Related

Use a subtype with mypy

I have a function that takes a list of objects and prints it.
bc_directives = t.Union[
data.Open,
data.Close,
data.Commodity,
data.Balance,
data.Pad,
data.Transaction,
data.Note,
data.Event,
data.Query,
data.Price,
data.Document,
data.Custom,
]
def print_entries(entries: t.List[bc_directives], file: t.IO) -> None:
pass
but if I do :
accounts: t.List[bc_directives] = []
for entry in data.sorted(entries):
if isinstance(entry, data.Open):
accounts.append(entry)
continue
accounts = sorted(accounts, key=lambda acc: acc.account)
# the attribute account does not exist for the other class.
print_entries(accounts)
Here I have a problem.
mypy complain that the other class does not have account attribute. Of course it is designed like that.
Item "Commodity" of "Union[Open, Close, Commodity, Balance, Pad, Transaction, Note, Event, Query, Price, Document, Custom]" has no attribute "account"
If I change the definition of accounts to t.List[data.Open], mypy complains when I used print_entries. (but it should be the best).
So how can I use use a subset of a union and get mypy to not complain?
You should make print_entries accept a Sequence, not a List. Here is a simplified example demonstrating a type-safe version of your code:
from typing import IO, List, Sequence, Union
class Open:
def __init__(self, account: int) -> None:
self.account = account
class Commodity: pass
Directives = Union[Open, Commodity]
def print_entries(entries: Sequence[Directives]) -> None:
for entry in entries:
print(entry)
accounts: List[Open] = [Open(1), Open(2), Open(3)]
print_entries(accounts)
The reason why making print_entries accept a list of your directive types is because it would introduce a potential bug in your code -- if print_entries were to do entries.append(Commodities()), your list of accounts would no longer contain only Open objects, breaking type safety.
Sequence is a read-only version of a list and so sidesteps this problem entirely, letting it have fewer restrictions. (That is, List[T] is a subclass of Sequence[T]).
More precisely, we say that Sequence is a covariant type: if if we have some child type C that subclasses a parent type P (if P :> C), it is always true that Sequence[P] :> Sequence[C].
In contrast, Lists are invariant: List[P] and List[C] will have no inherent relationship to each other, and neither subclasses the other.
Here is a tabular summary of the different kinds of relationships generic types can be designed to have:
| Foo[P] :> Foo[C] | Foo[C] :> Foo[P] | Used for
--------------------------------------------------------------------------------------
Covariant | True | False | Read-only types
Contravariant | False | True | Write-only types
Invariant | False | False | Both readable and writable types
Bivariant | True | True | Nothing (not type safe)

Is it possible to invoke python function with logical statement as parameter?

I have found a weird function invocation while reading models.py file in python requests library. I tried to find some explanations in python official documentation but without any successes, unfortunately. Do you possibly know why such a case is possible or how to use logical operators in functions invocation? Are those a part of good practices? Please, find the code below.
fields = to_key_val_list(data or {})
files = to_key_val_list(files or {})
This kind of things are used very often in python programming language
fields = to_key_val_list(data or {}) # this means, that if boolean value of data variable is False, use empty dict/or anything you want.
Also,,,
class Foo:
def __init__(self, data: list):
self.data = data or 'abc' # if data will be empty list self.data will become 'abc'
You can use and also. and/or both are available.
val = a or b or c # in the chain, if a is False, value of val would become b. if be is False also, then c
val = a and b and c # "and" checks values of whole chain. if a is False, so val will have same value as a. if all is true in chain, the last element value will be inside val.

Is it possible to have a scenario outline table with empty values?

Scenaio Outline: Blah de blah
When I enter and on the input field
Then Everything is good
Examples:
| a | b |
| 1 | 2 |
| | 3 |
The above scenario throws the following error in BBD Behave
Test undefined
Please define test
I am not sure how I can come around this.
Any suggestions?
Use Custom Type Conversions described in https://pypi.org/project/parse/
import parse
from behave import given, register_type
#parse.with_pattern(r'.*')
def parse_nullable_string(text):
return text
register_type(NullableString=parse_nullable_string)
#given('params "{a:NullableString}" and "{b:NullableString}"'
def set_params(context, a, b):
# a or b will be empty if they are blank in the Examples
context.a = a
context.b = b
Now the feature file could look like this,
Given params "<a>" and "<b>"
# Rest of the steps
Examples:
| a | b |
| 1 | 2 |
| | 3 |
It is indeed possible to use empty table cells (as in your example, not using "" or something) if you can go without explicitly mentioning your parameters in your given/when/then steps.
In your example, that would mean that you must not write your step definitions like this
Given two parameters <a> and <b>
...
#given('two parameters {a} and {b}
def step(context, a, b):
# test something with a and b
but rather like this:
Given two parameters a and b # <-- note the missing angle brackets
...
#given('two parameters a and b') <-- note the missing curly brackets
def step(context): # <-- note the missing function arguments for a and b
# ...
Now, in order to access the current table row, you can use context.active_outline (which is a bit hidden in the appendix of the documentation).
context.active_outline returns a behave.model.row object which can be accessed in the following ways:
context.active_outline.headings returns a list of the table headers, no matter what the currently iterated row is (a and b in the example from the question )
context.active_outline.cells returns a list of the cell values for the currently iterated row (1, 2 and '' (empty string that can be tested with if not...), 3 in the example from the question)
index-based access like context.active_outline[0] returns the cell value from the first column (no matter the heading) etc.
named-based access like context.active_outline['a'] returns the cell value for the column with the a header, no matter its index
As context.active_outline.headings and context.active_outline.cells return lists, one can also do useful stuff like for heading, cell in zip(context.active_outline.headings, context.active_outline.cells) to iterate over the heading-value pairs etc.
As far as I know you can't do it. But you can use either an empty string or a placeholder value (e.g. 'N/A') that you can look out for in your step definitions.

Python 3 changing value of dictionary key in for loop not working

I have python 3 code that is not working as expected:
def addFunc(x,y):
print (x+y)
def subABC(x,y,z):
print (x-y-z)
def doublePower(base,exp):
print(2*base**exp)
def RootFunc(inputDict):
for k,v in inputDict.items():
if v[0]==1:
d[k] = addFunc(*v[1:])
elif v[0] ==2:
d[k] = subABC(*v[1:])
elif v[0]==3:
d[k] = doublePower(*v[1:])
d={"s1_7":[1,5,2],"d1_6":[2,12,3,3],"e1_3200":[3,40,2],"s2_13":[1,6,7],"d2_30":[2,42,2,10]}
RootFunc(d)
#test to make sure key var assignment works
print(d)
I get:
{'d2_30': None, 's2_13': None, 's1_7': None, 'e1_3200': None, 'd1_6': None}
I expected:
{'d2_30': 30, 's2_13': 13, 's1_7': 7, 'e1_3200': 3200, 'd1_6': 6}
What's wrong?
Semi related: I know dictionaries are unordered but is there any reason why python picked this order? Does it run the keys through a randomizer?
print does not return a value. It returns None, so every time you call your functions, they're printing to standard output and returning None. Try changing all print statements to return like so:
def addFunc(x,y):
return x+y
This will give the value x+y back to whatever called the function.
Another problem with your code (unless you meant to do this) is that you define a dictionary d and then when you define your function, you are working on this dictionary d and not the dictionary that is 'input':
def RootFunc(inputDict):
for k,v in inputDict.items():
if v[0]==1:
d[k] = addFunc(*v[1:])
Are you planning to always change d and not the dictionary that you are iterating over, inputDict?
There may be other issues as well (accepting a variable number of arguments within your functions, for instance), but it's good to address one problem at a time.
Additional Notes on Functions:
Here's some sort-of pseudocode that attempts to convey how functions are often used:
def sample_function(some_data):
modified_data = []
for element in some_data:
do some processing
add processed crap to modified_data
return modified_data
Functions are considered 'black box', which means you structure them so that you can dump some data into them and they always do the same stuff and you can call them over and over again. They will either return values or yield values or update some value or attribute or something (the latter are called 'side effects'). For the moment, just pay attention to the return statement.
Another interesting thing is that functions have 'scope' which means that when I just defined it with a fake-name for the argument, I don't actually have to have a variable called "some_data". I can pass whatever I want to the function, but inside the function I can refer to the fake name and create other variables that really only matter within the context of the function.
Now, if we run my function above, it will go ahead and process the data:
sample_function(my_data_set)
But this is often kind of pointless because the function is supposed to return something and I didn't do anything with what it returned. What I should do is assign the value of the function and its arguments to some container so I can keep the processed information.
my_modified_data = sample_function(my_data_set)
This is a really common way to use functions and you'll probably see it again.
One Simple Way to Approach Your Problem:
Taking all this into consideration, here is one way to solve your problem that comes from a really common programming paradigm:
def RootFunc(inputDict):
temp_dict = {}
for k,v in inputDict.items():
if v[0]==1:
temp_dict[k] = addFunc(*v[1:])
elif v[0] ==2:
temp_dict[k] = subABC(*v[1:])
elif v[0]==3:
temp_dict[k] = doublePower(*v[1:])
return temp_dict
inputDict={"s1_7":[1,5,2],"d1_6":[2,12,3,3],"e1_3200":[3,40,2],"s2_13":[1,6,7],"d2_30"[2,42,2,10]}
final_dict = RootFunc(inputDict)
As erewok stated, you are using "print" and not "return" which may be the source of your error. And as far as the ordering is concerned, you already know that dictionaries are unordered, according to python doc at least, the ordering is not random, but rather implemented as hash tables.
Excerpt from the python doc: [...]A mapping object maps hashable values to arbitrary objects. Mappings are mutable objects. There is currently only one standard mapping type, the dictionary. [...]
Now key here is that the order of the element is not really random. I have often noticed that the order stays the same no matter how I construct a dictionary on some values... using lambda or just creating it outright, the order has always remained the same, so it can't be random, but it's definitely arbitrary.

Semantics of python loops and strings

Consider:
args = ['-sdfkj']
print args
for arg in args:
print arg.replace("-", '')
arg = arg.replace("-", '')
print args
This yields:
['-sdfkj']
sdfkj
['-sdfkj']
Where I expected it to be ['sdfkj'].
Is arg in the loop a copy?
It behaves as if it is a copy (or perhaps an immutable thingie, but then I expect an error would be thrown...)
Note: I can get the right behavior with a list comprehension. I am curious as to the cause of the above behavior.
Is arg in the loop a copy?
Yes, it contains a copy of the reference.
When you reassign arg you aren't modifying the original array, nor the string inside it (strings are immutable). You modify only what the local variable arg points to.
Before assignment After assignment
args arg args arg
| | | |
| | | |
(array) / (array) 'sdfkj'
|[0] / |[0]
\ / |
\ / |
'-sdfkj' '-sdfkj'
Since you mention in your question that you know it can be done using list comprehensions, I'm not going to show you that way.
What is happening there is that the reference to each value is copied into the variable arg. Initially they both refer to the same variable. Once arg is reassigned, it refers to the newly created variable, while the reference in the list remains unchanged. It has nothing to do with the fact that strings are immutable in Python. Try it out using mutable types.
A non-list comprehension way would be to modify the list in place:
for i in xrange(len(args)):
args[i]=args[i].replace('-','')
print args
If you want to modify the actual list you have to specifically assign the changes to the list 'args.'
i.e.
for arg in args:
if arg == "-":
args[arg] = args[arg].replace("-", '')
for a list I'd try:
args = [x.replace("-", '') for x in args]

Categories

Resources