From ee641c189f124c02495de6cf38b863a36e427988 Mon Sep 17 00:00:00 2001 From: adii1823 <64855277+adii1823@users.noreply.github.com> Date: Thu, 28 Oct 2021 17:37:54 +0530 Subject: [PATCH] ch04 --- ch04/arguments.combined.py | 8 +++ ch04/arguments.keyword.py | 5 ++ ch04/arguments.multiple.value.py | 13 +++++ ch04/arguments.positional.keyword.py | 15 +++++ ch04/arguments.positional.py | 5 ++ ch04/arguments.unpack.dict.py | 6 ++ ch04/arguments.unpack.iterable.py | 6 ++ ch04/data.science.example.py | 22 +++++++ ch04/docstrings.py | 24 ++++++++ ch04/filter.lambda.py | 6 ++ ch04/filter.regular.py | 10 ++++ ch04/func.attributes.py | 16 +++++ ch04/func_from.py | 5 ++ ch04/func_import.py | 6 ++ ch04/imports.py | 11 ++++ ch04/key.points.argument.passing.py | 6 ++ ch04/key.points.assignment.py | 7 +++ ch04/key.points.mutable.assignment.py | 8 +++ ch04/key.points.mutable.py | 7 +++ ch04/lambda.explained.py | 30 ++++++++++ ch04/lib/__init__.py | 0 ch04/lib/funcdef.py | 6 ++ ch04/matrix.multiplication.func.py | 12 ++++ ch04/matrix.multiplication.nofunc.py | 7 +++ ch04/no.side.effects.py | 10 ++++ ch04/parameters.all.pkwonly.py | 8 +++ ch04/parameters.all.py | 7 +++ ch04/parameters.default.py | 8 +++ ...ters.defaults.mutable.intermediate.call.py | 11 ++++ ch04/parameters.defaults.mutable.no.trap.py | 5 ++ ch04/parameters.defaults.mutable.py | 11 ++++ ch04/parameters.keyword.only.py | 16 +++++ ch04/parameters.positional.only.optional.py | 6 ++ ch04/parameters.positional.only.py | 58 +++++++++++++++++++ ch04/parameters.variable.db.py | 15 +++++ ch04/parameters.variable.keyword.py | 7 +++ ch04/parameters.variable.positional.py | 12 ++++ ch04/primes.py | 47 +++++++++++++++ ch04/recursive.factorial.py | 8 +++ ch04/return.multiple.py | 26 +++++++++ ch04/return.none.py | 7 +++ ch04/return.single.value.2.py | 12 ++++ ch04/return.single.value.py | 11 ++++ ch04/scoping.level.1.py | 9 +++ ch04/scoping.level.2.global.py | 16 +++++ ch04/scoping.level.2.nonlocal.py | 16 +++++ ch04/scoping.level.2.py | 15 +++++ ch04/vat.function.py | 7 +++ ch04/vat.py | 12 ++++ 49 files changed, 601 insertions(+) create mode 100644 ch04/arguments.combined.py create mode 100644 ch04/arguments.keyword.py create mode 100644 ch04/arguments.multiple.value.py create mode 100644 ch04/arguments.positional.keyword.py create mode 100644 ch04/arguments.positional.py create mode 100644 ch04/arguments.unpack.dict.py create mode 100644 ch04/arguments.unpack.iterable.py create mode 100644 ch04/data.science.example.py create mode 100644 ch04/docstrings.py create mode 100644 ch04/filter.lambda.py create mode 100644 ch04/filter.regular.py create mode 100644 ch04/func.attributes.py create mode 100644 ch04/func_from.py create mode 100644 ch04/func_import.py create mode 100644 ch04/imports.py create mode 100644 ch04/key.points.argument.passing.py create mode 100644 ch04/key.points.assignment.py create mode 100644 ch04/key.points.mutable.assignment.py create mode 100644 ch04/key.points.mutable.py create mode 100644 ch04/lambda.explained.py create mode 100644 ch04/lib/__init__.py create mode 100644 ch04/lib/funcdef.py create mode 100644 ch04/matrix.multiplication.func.py create mode 100644 ch04/matrix.multiplication.nofunc.py create mode 100644 ch04/no.side.effects.py create mode 100644 ch04/parameters.all.pkwonly.py create mode 100644 ch04/parameters.all.py create mode 100644 ch04/parameters.default.py create mode 100644 ch04/parameters.defaults.mutable.intermediate.call.py create mode 100644 ch04/parameters.defaults.mutable.no.trap.py create mode 100644 ch04/parameters.defaults.mutable.py create mode 100644 ch04/parameters.keyword.only.py create mode 100644 ch04/parameters.positional.only.optional.py create mode 100644 ch04/parameters.positional.only.py create mode 100644 ch04/parameters.variable.db.py create mode 100644 ch04/parameters.variable.keyword.py create mode 100644 ch04/parameters.variable.positional.py create mode 100644 ch04/primes.py create mode 100644 ch04/recursive.factorial.py create mode 100644 ch04/return.multiple.py create mode 100644 ch04/return.none.py create mode 100644 ch04/return.single.value.2.py create mode 100644 ch04/return.single.value.py create mode 100644 ch04/scoping.level.1.py create mode 100644 ch04/scoping.level.2.global.py create mode 100644 ch04/scoping.level.2.nonlocal.py create mode 100644 ch04/scoping.level.2.py create mode 100644 ch04/vat.function.py create mode 100644 ch04/vat.py diff --git a/ch04/arguments.combined.py b/ch04/arguments.combined.py new file mode 100644 index 0000000..c856aa7 --- /dev/null +++ b/ch04/arguments.combined.py @@ -0,0 +1,8 @@ +# arguments.combined.py +def func(a, b, c, d, e, f): + print(a, b, c, d, e, f) + +func(1, *(2, 3), f=6, *(4, 5)) +func(*(1, 2), e=5, *(3, 4), f=6) +func(1, **{'b': 2, 'c': 3}, d=4, **{'e': 5, 'f': 6}) +func(c=3, *(1, 2), **{'d': 4}, e=5, **{'f': 6}) diff --git a/ch04/arguments.keyword.py b/ch04/arguments.keyword.py new file mode 100644 index 0000000..3bc4ea9 --- /dev/null +++ b/ch04/arguments.keyword.py @@ -0,0 +1,5 @@ +# arguments.keyword.py +def func(a, b, c): + print(a, b, c) + +func(a=1, c=2, b=3) # prints: 1 3 2 diff --git a/ch04/arguments.multiple.value.py b/ch04/arguments.multiple.value.py new file mode 100644 index 0000000..b4cbe17 --- /dev/null +++ b/ch04/arguments.multiple.value.py @@ -0,0 +1,13 @@ +# arguments.multiple.value.py +def func(a, b, c): + print(a, b, c) + +func(2, 3, a=1) + +""" +$ python arguments.multiple.value.py +Traceback (most recent call last): + File "arguments.multiple.value.py", line 5, in + func(2, 3, a=1) +TypeError: func() got multiple values for argument 'a' +""" diff --git a/ch04/arguments.positional.keyword.py b/ch04/arguments.positional.keyword.py new file mode 100644 index 0000000..f6b591f --- /dev/null +++ b/ch04/arguments.positional.keyword.py @@ -0,0 +1,15 @@ +# arguments.positional.keyword.py +def func(a, b, c): + print(a, b, c) + +func(42, b=1, c=2) + +func(b=1, c=2, 42) # positional argument after keyword arguments + +""" +$ python arguments.positional.keyword.py + File "arguments.positional.keyword.py", line 7 + func(b=1, c=2, 42) # positional argument after keyword arguments + ^ +SyntaxError: positional argument follows keyword argument +""" diff --git a/ch04/arguments.positional.py b/ch04/arguments.positional.py new file mode 100644 index 0000000..b9ab8b4 --- /dev/null +++ b/ch04/arguments.positional.py @@ -0,0 +1,5 @@ +# arguments.positional.py +def func(a, b, c): + print(a, b, c) + +func(1, 2, 3) # prints: 1 2 3 diff --git a/ch04/arguments.unpack.dict.py b/ch04/arguments.unpack.dict.py new file mode 100644 index 0000000..28f2fec --- /dev/null +++ b/ch04/arguments.unpack.dict.py @@ -0,0 +1,6 @@ +# arguments.unpack.dict.py +def func(a, b, c): + print(a, b, c) + +values = {'b': 1, 'c': 2, 'a': 42} +func(**values) # equivalent to func(b=1, c=2, a=42) diff --git a/ch04/arguments.unpack.iterable.py b/ch04/arguments.unpack.iterable.py new file mode 100644 index 0000000..31bf7ac --- /dev/null +++ b/ch04/arguments.unpack.iterable.py @@ -0,0 +1,6 @@ +# arguments.unpack.iterable.py +def func(a, b, c): + print(a, b, c) + +values = (1, 3, -7) +func(*values) # equivalent to: func(1, 3, -7) diff --git a/ch04/data.science.example.py b/ch04/data.science.example.py new file mode 100644 index 0000000..f2bcb69 --- /dev/null +++ b/ch04/data.science.example.py @@ -0,0 +1,22 @@ +# data.science.example.py +def do_report(data_source): + # fetch and prepare data + data = fetch_data(data_source) + parsed_data = parse_data(data) + filtered_data = filter_data(parsed_data) + polished_data = polish_data(filtered_data) + + # run algorithms on data + final_data = analyse(polished_data) + + # create and return report + report = Report(final_data) + return report + + +if __name__ == "__main__": + + print( + "Please don't call the `do_report` function. " + "It's just and example." + ) diff --git a/ch04/docstrings.py b/ch04/docstrings.py new file mode 100644 index 0000000..f335062 --- /dev/null +++ b/ch04/docstrings.py @@ -0,0 +1,24 @@ +# docstrings.py +def square(n): + """Return the square of a number n. """ + return n ** 2 + +def get_username(userid): + """Return the username of a user given their id. """ + return db.get(user_id=userid).username + + +def connect(host, port, user, password): + """Connect to a database. + + Connect to a PostgreSQL database directly, using the given + parameters. + + :param host: The host IP. + :param port: The desired port. + :param user: The connection username. + :param password: The connection password. + :return: The connection object. + """ + # body of the function here... + return connection diff --git a/ch04/filter.lambda.py b/ch04/filter.lambda.py new file mode 100644 index 0000000..b8bc386 --- /dev/null +++ b/ch04/filter.lambda.py @@ -0,0 +1,6 @@ +# filter.lambda.py +def get_multiples_of_five(n): + return list(filter(lambda k: not k % 5, range(n))) + + +print(get_multiples_of_five(50)) diff --git a/ch04/filter.regular.py b/ch04/filter.regular.py new file mode 100644 index 0000000..1616437 --- /dev/null +++ b/ch04/filter.regular.py @@ -0,0 +1,10 @@ +# filter.regular.py +def is_multiple_of_five(n): + return not n % 5 + + +def get_multiples_of_five(n): + return list(filter(is_multiple_of_five, range(n))) + + +print(get_multiples_of_five(50)) diff --git a/ch04/func.attributes.py b/ch04/func.attributes.py new file mode 100644 index 0000000..dfe85f2 --- /dev/null +++ b/ch04/func.attributes.py @@ -0,0 +1,16 @@ +# func.attributes.py +def multiplication(a, b=1): + """Return a multiplied by b. """ + return a * b + + +if __name__ == "__main__": + + special_attributes = [ + "__doc__", "__name__", "__qualname__", "__module__", + "__defaults__", "__code__", "__globals__", "__dict__", + "__closure__", "__annotations__", "__kwdefaults__", + ] + + for attribute in special_attributes: + print(attribute, '->', getattr(multiplication, attribute)) diff --git a/ch04/func_from.py b/ch04/func_from.py new file mode 100644 index 0000000..c79b72a --- /dev/null +++ b/ch04/func_from.py @@ -0,0 +1,5 @@ +# func_from.py +from lib.funcdef import square, cube + +print(square(10)) +print(cube(10)) diff --git a/ch04/func_import.py b/ch04/func_import.py new file mode 100644 index 0000000..a9a365c --- /dev/null +++ b/ch04/func_import.py @@ -0,0 +1,6 @@ +# func_import.py +import lib.funcdef + + +print(lib.funcdef.square(10)) +print(lib.funcdef.cube(10)) diff --git a/ch04/imports.py b/ch04/imports.py new file mode 100644 index 0000000..c69d663 --- /dev/null +++ b/ch04/imports.py @@ -0,0 +1,11 @@ +# imports.py +from datetime import datetime, timezone # two imports on the same line +from unittest.mock import patch # single import + +import pytest # third party library + +from core.models import ( # multiline import + Exam, + Exercise, + Solution, +) diff --git a/ch04/key.points.argument.passing.py b/ch04/key.points.argument.passing.py new file mode 100644 index 0000000..5a3ca43 --- /dev/null +++ b/ch04/key.points.argument.passing.py @@ -0,0 +1,6 @@ +# key.points.argument.passing.py +x = 3 +def func(y): + print(y) + +func(x) # prints: 3 diff --git a/ch04/key.points.assignment.py b/ch04/key.points.assignment.py new file mode 100644 index 0000000..440f577 --- /dev/null +++ b/ch04/key.points.assignment.py @@ -0,0 +1,7 @@ +# key.points.assignment.py +x = 3 +def func(x): + x = 7 # defining a local x, not changing the global one + +func(x) +print(x) # prints: 3 diff --git a/ch04/key.points.mutable.assignment.py b/ch04/key.points.mutable.assignment.py new file mode 100644 index 0000000..458ca86 --- /dev/null +++ b/ch04/key.points.mutable.assignment.py @@ -0,0 +1,8 @@ +# key.points.mutable.assignment.py +x = [1, 2, 3] +def func(x): + x[1] = 42 # this changes the original `x` argument! + x = 'something else' # this points x to a new string object + +func(x) +print(x) # still prints: [1, 42, 3] diff --git a/ch04/key.points.mutable.py b/ch04/key.points.mutable.py new file mode 100644 index 0000000..16ac26d --- /dev/null +++ b/ch04/key.points.mutable.py @@ -0,0 +1,7 @@ +# key.points.mutable.py +x = [1, 2, 3] +def func(x): + x[1] = 42 # this affects the `x` argument! + +func(x) +print(x) # prints: [1, 42, 3] diff --git a/ch04/lambda.explained.py b/ch04/lambda.explained.py new file mode 100644 index 0000000..cbed5e5 --- /dev/null +++ b/ch04/lambda.explained.py @@ -0,0 +1,30 @@ +# lambda.explained.py +""" +myfunc = lambda [parameter_list]: expression + +def myfunc([parameter_list]): + return expression +""" + +# example 1: adder +def adder(a, b): + return a + b + +# is equivalent to: +adder_lambda = lambda a, b: a + b + +# example 2: to uppercase +def to_upper(s): + return s.upper() + +# is equivalent to: +to_upper_lambda = lambda s: s.upper() + + +if __name__ == "__main__": + + print(adder(3, 4)) + print(adder_lambda(3, 4)) + + print(to_upper("Hello")) + print(to_upper_lambda("Hello")) diff --git a/ch04/lib/__init__.py b/ch04/lib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ch04/lib/funcdef.py b/ch04/lib/funcdef.py new file mode 100644 index 0000000..6130290 --- /dev/null +++ b/ch04/lib/funcdef.py @@ -0,0 +1,6 @@ +# lib/funcdef.py +def square(n): + return n ** 2 + +def cube(n): + return n ** 3 diff --git a/ch04/matrix.multiplication.func.py b/ch04/matrix.multiplication.func.py new file mode 100644 index 0000000..6dca351 --- /dev/null +++ b/ch04/matrix.multiplication.func.py @@ -0,0 +1,12 @@ +# matrix.multiplication.func.py +# this function could also be defined in another module +def matrix_mul(a, b): + return [[sum(i * j for i, j in zip(r, c)) for c in zip(*b)] + for r in a] + + +a = [[1, 2], [3, 4]] +b = [[5, 1], [2, 1]] + +c = matrix_mul(a, b) +print(c) diff --git a/ch04/matrix.multiplication.nofunc.py b/ch04/matrix.multiplication.nofunc.py new file mode 100644 index 0000000..f023bba --- /dev/null +++ b/ch04/matrix.multiplication.nofunc.py @@ -0,0 +1,7 @@ +# matrix.multiplication.nofunc.py +a = [[1, 2], [3, 4]] +b = [[5, 1], [2, 1]] + +c = [[sum(i * j for i, j in zip(r, c)) for c in zip(*b)] + for r in a] +print(c) diff --git a/ch04/no.side.effects.py b/ch04/no.side.effects.py new file mode 100644 index 0000000..eee7a02 --- /dev/null +++ b/ch04/no.side.effects.py @@ -0,0 +1,10 @@ +# no.side.effects.py +# This file is not meant to be run +>>> numbers = [4, 1, 7, 5] +>>> sorted(numbers) # won't sort the original `numbers` list +[1, 4, 5, 7] +>>> numbers # let's verify +[4, 1, 7, 5] # good, untouched +>>> numbers.sort() # this will act on the list +>>> numbers +[1, 4, 5, 7] diff --git a/ch04/parameters.all.pkwonly.py b/ch04/parameters.all.pkwonly.py new file mode 100644 index 0000000..c87624e --- /dev/null +++ b/ch04/parameters.all.pkwonly.py @@ -0,0 +1,8 @@ +# parameters.all.pkwonly.py +def allparams(a, /, b, c=42, *args, d=256, e, **kwargs): + print('a, b, c:', a, b, c) + print('d, e:', d, e) + print('args:', args) + print('kwargs:', kwargs) + +allparams(1, 2, 3, 4, 5, 6, e=7, f=9, g=10) diff --git a/ch04/parameters.all.py b/ch04/parameters.all.py new file mode 100644 index 0000000..cbad779 --- /dev/null +++ b/ch04/parameters.all.py @@ -0,0 +1,7 @@ +# parameters.all.py +def func(a, b, c=7, *args, **kwargs): + print('a, b, c:', a, b, c) + print('args:', args) + print('kwargs:', kwargs) + +func(1, 2, 3, 5, 7, 9, A='a', B='b') diff --git a/ch04/parameters.default.py b/ch04/parameters.default.py new file mode 100644 index 0000000..1e9672e --- /dev/null +++ b/ch04/parameters.default.py @@ -0,0 +1,8 @@ +# parameters.default.py +def func(a, b=4, c=88): + print(a, b, c) + +func(1) # prints: 1 4 88 +func(b=5, a=7, c=9) # prints: 7 5 9 +func(42, c=9) # prints: 42 4 9 +func(42, 43, 44) # prints: 42, 43, 44 diff --git a/ch04/parameters.defaults.mutable.intermediate.call.py b/ch04/parameters.defaults.mutable.intermediate.call.py new file mode 100644 index 0000000..ac216c2 --- /dev/null +++ b/ch04/parameters.defaults.mutable.intermediate.call.py @@ -0,0 +1,11 @@ +# parameters.defaults.mutable.intermediate.call.py +def func(a=[], b={}): + print(a) + print(b) + print('#' * 12) + a.append(len(a)) # this will affect a's default value + b[len(a)] = len(a) # and this will affect b's one + +func() +func(a=[1, 2, 3], b={'B': 1}) +func() diff --git a/ch04/parameters.defaults.mutable.no.trap.py b/ch04/parameters.defaults.mutable.no.trap.py new file mode 100644 index 0000000..bf9c4de --- /dev/null +++ b/ch04/parameters.defaults.mutable.no.trap.py @@ -0,0 +1,5 @@ +# parameters.defaults.mutable.no.trap.py +def func(a=None): + if a is None: + a = [] + # do whatever you want with `a` ... diff --git a/ch04/parameters.defaults.mutable.py b/ch04/parameters.defaults.mutable.py new file mode 100644 index 0000000..59ee6ce --- /dev/null +++ b/ch04/parameters.defaults.mutable.py @@ -0,0 +1,11 @@ +# parameters.defaults.mutable.py +def func(a=[], b={}): + print(a) + print(b) + print('#' * 12) + a.append(len(a)) # this will affect a's default value + b[len(a)] = len(a) # and this will affect b's one + +func() +func() +func() diff --git a/ch04/parameters.keyword.only.py b/ch04/parameters.keyword.only.py new file mode 100644 index 0000000..b33b2b2 --- /dev/null +++ b/ch04/parameters.keyword.only.py @@ -0,0 +1,16 @@ +# parameters.keyword.only.py +def kwo(*a, c): + print(a, c) + +kwo(1, 2, 3, c=7) # prints: (1, 2, 3) 7 +kwo(c=4) # prints: () 4 +# kwo(1, 2) # breaks, invalid syntax, with the following error +# TypeError: kwo() missing 1 required keyword-only argument: 'c' + +def kwo2(a, b=42, *, c): + print(a, b, c) + +kwo2(3, b=7, c=99) # prints: 3 7 99 +kwo2(3, c=13) # prints: 3 42 13 +# kwo2(3, 23) # breaks, invalid syntax, with the following error +# TypeError: kwo2() missing 1 required keyword-only argument: 'c' diff --git a/ch04/parameters.positional.only.optional.py b/ch04/parameters.positional.only.optional.py new file mode 100644 index 0000000..1c5ba36 --- /dev/null +++ b/ch04/parameters.positional.only.optional.py @@ -0,0 +1,6 @@ +# parameters.positional.only.optional.py +def func(a, b=2, /): + print(a, b) + +func(4, 5) # prints 4 5 +func(3) # prints 3 2 diff --git a/ch04/parameters.positional.only.py b/ch04/parameters.positional.only.py new file mode 100644 index 0000000..828ff40 --- /dev/null +++ b/ch04/parameters.positional.only.py @@ -0,0 +1,58 @@ +# parameters.positional.only.py +def func(a, b, /, c): + print(a, b, c) + +func(1, 2, 3) # prints: 1 2 3 +func(1, 2, c=3) # prints 1 2 3 +# func(1, b=2, c=3) # produces the following traceback: +""" +Traceback (most recent call last): + File "arguments.positional.only.py", line 7, in + func(1, b=2, c=3) +TypeError: func() got some positional-only arguments +passed as keyword arguments: 'b' +""" + +""" +def func_name(positional_only_parameters, /, + positional_or_keyword_parameters, *, + keyword_only_parameters): + + +Valid: + +def func_name(p1, p2, /, p_or_kw, *, kw): +def func_name(p1, p2=None, /, p_or_kw=None, *, kw): +def func_name(p1, p2=None, /, *, kw): +def func_name(p1, p2=None, /): +def func_name(p1, p2, /, p_or_kw): +def func_name(p1, p2, /): + + +Invalid: + +def func_name(p1, p2=None, /, p_or_kw, *, kw): +def func_name(p1=None, p2, /, p_or_kw=None, *, kw): +def func_name(p1=None, p2, /): + + +Why it is useful: + +def divmod(a, b, /): + "Emulate the built in divmod() function" + return (a // b, a % b) + + +len(obj='hello') # The "obj" keyword argument impairs readability +""" + +def func_name(name, /, **kwargs): + print(name) + print(kwargs) + +func_name('Positional-only name', name='Name in **kwargs') +""" +Prints: +Positional-only name +{'name': 'Name in **kwargs'} +""" diff --git a/ch04/parameters.variable.db.py b/ch04/parameters.variable.db.py new file mode 100644 index 0000000..c8205e2 --- /dev/null +++ b/ch04/parameters.variable.db.py @@ -0,0 +1,15 @@ +# parameters.variable.db.py +def connect(**options): + conn_params = { + 'host': options.get('host', '127.0.0.1'), + 'port': options.get('port', 5432), + 'user': options.get('user', ''), + 'pwd': options.get('pwd', ''), + } + print(conn_params) + # we then connect to the db (commented out) + # db.connect(**conn_params) + +connect() +connect(host='127.0.0.42', port=5433) +connect(port=5431, user='fab', pwd='gandalf') diff --git a/ch04/parameters.variable.keyword.py b/ch04/parameters.variable.keyword.py new file mode 100644 index 0000000..9240a1c --- /dev/null +++ b/ch04/parameters.variable.keyword.py @@ -0,0 +1,7 @@ +# parameters.variable.keyword.py +def func(**kwargs): + print(kwargs) + +func(a=1, b=42) # prints {'a': 1, 'b': 42} +func() # prints {} +func(a=1, b=46, c=99) # prints {'a': 1, 'b': 46, 'c': 99} diff --git a/ch04/parameters.variable.positional.py b/ch04/parameters.variable.positional.py new file mode 100644 index 0000000..a52d4e5 --- /dev/null +++ b/ch04/parameters.variable.positional.py @@ -0,0 +1,12 @@ +# parameters.variable.positional.py +def minimum(*n): + # print(type(n)) # n is a tuple + if n: # explained after the code + mn = n[0] + for value in n[1:]: + if value < mn: + mn = value + print(mn) + +minimum(1, 3, -7, 9) # n = (1, 3, -7, 9) - prints: -7 +minimum() # n = () - prints: nothing diff --git a/ch04/primes.py b/ch04/primes.py new file mode 100644 index 0000000..27f1c00 --- /dev/null +++ b/ch04/primes.py @@ -0,0 +1,47 @@ +# primes.py +from math import sqrt, ceil + + +def get_primes(n): + """Calculate a list of primes up to n (included). """ + primelist = [] + for candidate in range(2, n + 1): + is_prime = True + root = ceil(sqrt(candidate)) # division limit + for prime in primelist: # we try only the primes + if prime > root: # no need to check any further + break + if candidate % prime == 0: + is_prime = False + break + if is_prime: + primelist.append(candidate) + return primelist + + +if __name__ == "__main__": + + def test(): + primes = get_primes(10**3) + primes2 = [ + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, + 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, + 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, + 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, + 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, + 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, + 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, + 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, + 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, + 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, + 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, + 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, + 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, + 941, 947, 953, 967, 971, 977, 983, 991, 997 + ] + return primes == primes2 + + print(test()) + + print(get_primes(100)) diff --git a/ch04/recursive.factorial.py b/ch04/recursive.factorial.py new file mode 100644 index 0000000..a629b3d --- /dev/null +++ b/ch04/recursive.factorial.py @@ -0,0 +1,8 @@ +# recursive.factorial.py +def factorial(n): + if n in (0, 1): # base case + return 1 + return factorial(n - 1) * n # recursive case + + +print([factorial(n) for n in range(10)]) diff --git a/ch04/return.multiple.py b/ch04/return.multiple.py new file mode 100644 index 0000000..00fac92 --- /dev/null +++ b/ch04/return.multiple.py @@ -0,0 +1,26 @@ +# return.multiple.py +def moddiv(a, b): + return a // b, a % b + + +def test(n=10**4): + from random import choice, random, randint + m = 10 ** 6 + for x in range(n): + a = choice((randint(0, m), m * random())) + b = 0 + while not b: + b = choice((randint(1, m), m * random())) + + r = divmod(a, b) + r2 = moddiv(a, b) + if r != r2: + print('Difference: ', a, b, r, r2) + + +if __name__ == "__main__": + + test(10 ** 6) + print('Done') + + print(moddiv(20, 7)) # prints (2, 6) diff --git a/ch04/return.none.py b/ch04/return.none.py new file mode 100644 index 0000000..9e246f8 --- /dev/null +++ b/ch04/return.none.py @@ -0,0 +1,7 @@ +# return.none.py +def func(): + pass + +func() # the return of this call won't be collected. It's lost. +a = func() # the return of this one instead is collected into `a` +print(a) # prints: None diff --git a/ch04/return.single.value.2.py b/ch04/return.single.value.2.py new file mode 100644 index 0000000..90f9c00 --- /dev/null +++ b/ch04/return.single.value.2.py @@ -0,0 +1,12 @@ +# return.single.value.2.py +from functools import reduce +from operator import mul + + +def factorial(n): + return reduce(mul, range(1, n + 1), 1) + + +f5 = factorial(5) # f5 = 120 +print(f5) +print([factorial(k) for k in range(10)]) diff --git a/ch04/return.single.value.py b/ch04/return.single.value.py new file mode 100644 index 0000000..dad0099 --- /dev/null +++ b/ch04/return.single.value.py @@ -0,0 +1,11 @@ +# return.single.value.py +def factorial(n): + if n in (0, 1): + return 1 + result = n + for k in range(2, n): + result *= k + return result + +f5 = factorial(5) # f5 = 120 +print(f5) diff --git a/ch04/scoping.level.1.py b/ch04/scoping.level.1.py new file mode 100644 index 0000000..b40a57a --- /dev/null +++ b/ch04/scoping.level.1.py @@ -0,0 +1,9 @@ +# scoping.level.1.py +def my_function(): + test = 1 # this is defined in the local scope of the function + print('my_function:', test) + + +test = 0 # this is defined in the global scope +my_function() +print('global:', test) diff --git a/ch04/scoping.level.2.global.py b/ch04/scoping.level.2.global.py new file mode 100644 index 0000000..67349e1 --- /dev/null +++ b/ch04/scoping.level.2.global.py @@ -0,0 +1,16 @@ +# scoping.level.2.global.py +def outer(): + test = 1 # outer scope + + def inner(): + global test + test = 2 # global scope + print('inner:', test) + + inner() + print('outer:', test) + + +test = 0 # global scope +outer() +print('global:', test) diff --git a/ch04/scoping.level.2.nonlocal.py b/ch04/scoping.level.2.nonlocal.py new file mode 100644 index 0000000..1e1c574 --- /dev/null +++ b/ch04/scoping.level.2.nonlocal.py @@ -0,0 +1,16 @@ +# scoping.level.2.nonlocal.py +def outer(): + test = 1 # outer scope + + def inner(): + nonlocal test + test = 2 # nearest enclosing scope (which is 'outer') + print('inner:', test) + + inner() + print('outer:', test) + + +test = 0 # global scope +outer() +print('global:', test) diff --git a/ch04/scoping.level.2.py b/ch04/scoping.level.2.py new file mode 100644 index 0000000..ac2dece --- /dev/null +++ b/ch04/scoping.level.2.py @@ -0,0 +1,15 @@ +# scoping.level.2.py +def outer(): + test = 1 # outer scope + + def inner(): + test = 2 # inner scope + print('inner:', test) + + inner() + print('outer:', test) + + +test = 0 # global scope +outer() +print('global:', test) diff --git a/ch04/vat.function.py b/ch04/vat.function.py new file mode 100644 index 0000000..954ffcc --- /dev/null +++ b/ch04/vat.function.py @@ -0,0 +1,7 @@ +# vat.function.py +def calculate_price_with_vat(price, vat): + return price * (100 + vat) / 100 + + +if __name__ == "__main__": + print(calculate_price_with_vat(100, 20)) diff --git a/ch04/vat.py b/ch04/vat.py new file mode 100644 index 0000000..cb0a1d3 --- /dev/null +++ b/ch04/vat.py @@ -0,0 +1,12 @@ +# vat.py +price = 100 # GBP, no VAT +final_price1 = price * 1.2 +final_price2 = price + price / 5.0 +final_price3 = price * (100 + 20) / 100.0 +final_price4 = price + price * 0.2 + + +if __name__ == "__main__": + for var, value in sorted(vars().items()): + if 'price' in var: + print(var, value)