DAY15

DAY15

递归

函数的嵌套调用是:函数嵌套函数。函数的递归调用:它是一种特殊的嵌套调用,但是它在调用一个函数的过程中,又直接或间接的调用了它自身。

如果递归函数不断地调用函数自身,那么这个递归函数将会进入一个死循环,因此我们应该给递归函数一个明确的结束条件。

直接调用

直接调用指的是:直接在函数内部调用函数自身。

import sys
print(f"最大递归层数:{sys.getrecursionlimit()}")

最大递归层数:3000

import sys

#修改递归层数
sys.getrecursionlimit(10000)
def foo(n):
    print('from foo',n)
    foo(n+1)
foo(0)

间接调用

间接调用指的是:不在原函数体内调用函数自身,而是通过其他的方法间接调用函数自身。

def bar():
    print('from bar')
    foo()
    
def foo():
    print('from foo')
    bar()
    
bar()

递归必须要有两个明确的阶段:

1.递推:一层一层递归调用下去,进入下一层递归的问题规模都将会减小

2.回溯:递归必须要有一个明确的结束条件,在满足该条件开始一层一层回溯。

递归的精髓在于通过不断地重复逼近一个最终结果。

为什么要用递归

递归的本质就是干重复的活,但是仅仅是普通的重复,我们使用while循环就可以了。

lis = [1, [2, [3, [4, [5, [6, ]]]]]]

def tell(lis):
    for i in lis:
        if type(i) is list:
            tell(i)
        else:
            print(i)
            
# print(f"tell(lis): {tell(lis)}")
tell(lis)

1
2
3
4
5
6

如何用递归

二分法的应用

有一个从小到大排列的整型数字列表,我们判断某一个数字是不是在这个列表里面。

nums = [1, 3, 7, 11, 22, 34, 55, 78, 111, 115]

for item in nums:
    if item == 10:
        print('find it')
        break
else:
    print('not exists')

not exists

对于上述的列表我们可能可以通过一个for循环实现我们需要的功能,但是当我们的列表中的元素个数非常多时,我们还用这种方法,那是极其复杂 ,因为我们可以考虑使用二分法的思想实现。

form random import randint
nums = [randint(1, 100) for i in range(100)]
nums = sorted(nums)
print(nums)

[1, 2, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 10, 11, 11, 11, 11, 12, 13, 13, 15, 16, 16, 20, 21, 21, 23, 24, 26, 26, 27, 28, 28, 31, 33, 33, 34, 35, 38, 38, 39, 40, 42, 43, 45, 45, 46, 46, 47, 47, 51, 52, 52, 53, 53, 55, 55, 56, 56, 57, 57, 57, 58, 59, 61, 62, 64, 66, 66, 67, 68, 69, 69, 71, 72, 72, 74, 74, 75, 76, 78, 78, 79, 79, 79, 79, 80, 82, 85, 88, 89, 90, 90, 91, 91, 91, 94, 99, 99, 100]

内置函数

更多内置函数:https://docs.python.org/3/library/functions.html?highlight=built#ascii

watermark

掌握

bytes()

解码字符。

res = '你好'.encide('utf8')
print(res)

b'\xe4\xbd\xa0\xe5\xa5\xbd'

res = bytes('你好', encoding = 'utf8')
print(res)

b'\xe4\xbd\xa0\xe5\xa5\xbd'

chr()/ord()

chr()参考ASCll码表将数字转成对应字符;ord()将字符转换成对应的数字。

print(chr(65))

A

print(ord('A'))

65

divmod()

分栏

print(divmod(10, 3))

(3 10)

enumerate()

带有索引的迭代

l = ['a', 'b', 'c']
for i in enumerate(1):
    print(i)

(0, 'a')
(1, 'b')
(2, 'c')

eval

把字符串翻译成数据类型。

lis = '[1, 2, 3]'
lis_eval = eval(lis)
print(lis_eval)

[1, 2, 3]

hash()

是否可哈希

print(hash(1))

1

了解

abs()

求绝对值

print(abs(-13))   #求绝对值

13

all()

可迭代对象内元素全为真,则返回真。

print(all([1, 2, 3, 0]))
print(all[])

False

True

any()

可迭代对象中有一元素为真,则为真。

print(any([1, 2, 3, 0]))
print(any([]))

True

False

bin()/oct()/hex()

二进制、八进制、十六进制转换。

print(bin(17))
print(oct(17))
print(hex(17))

0b10001

0o21

0x11

dir()

列举出所有time()的功能。

import time
print(dir(time))

['_STRUCT_TM_ITEMS', 'doc', 'loader', 'name', 'package', 'spec', 'altzone', 'asctime', 'clock', 'ctime', 'daylight', 'get_clock_info', 'gmtime', 'localtime', 'mktime', 'monotonic', 'perf_counter', 'process_time', 'sleep', 'strftime', 'strptime', 'struct_time', 'time', 'timezone', 'tzname', 'tzset']

frozenset()

不可变集合。

s = frozenset({1, 2, 3})
print(s)

frozenset({1, 2, 3})

globals()/loacals()

查看全局名字;查看局部名字。

# print(globals())
def func():
    a = 1
#    print(globals())
    print(locals())
    
func()

{'a': 1}

pow()

print(pow(3, 2, 3))  # (3**2)%3

0

9.round()

print(round(3.5))

4

10.slice()

lis = ['a', 'b', 'c']
s = slice(1, 4, 1)
print(lis[s])  # print(lis[1:4:1])

['b', 'c']

11.sum()

print(sum(range(100)))

4950

  1. import()

通过字符串导入模块。

m = __import__('time')
print(m.time())
1556607502.334777

面向对象知识点

  1. classmethod
  2. staticmethod
  3. property
  4. delattr
  5. hasattr
  6. getattr
  7. setattr
  8. isinstance()
  9. issubclass()
  10. object()
  11. super()

面向过程编程

面向过程编程是解决问题的一种思想,相当于武林门派,武林门派之间没有好坏之分,因此它与我们之后学习的面向对象编程其实没有好坏之分。

面向过程编程,核心是编程二字,过程指的是解决问题的步骤,即先干什么、后干什么、再干什么、然后干什么……

基于该思想编写程序就好比在设计一条流水线,面向对称编程其实是一种机械式的思维方式。

当我们写登录功能,我们首先需要输入账号、密码,然后认证两次密码是否相同,然后从数据库中读取密码验证用户密码输入是否正确,然后输入验证码……之后,我们就能够实现登录功能。这样把登录功能问题流程化,进而是解决问题的思路非常清晰。

优点:复杂的问题流程化,进而简单化。

生产汽水瓶的流水线,没办法生产特斯拉。流水线下一个阶段的输入与上一个阶段的输出是有关联的。因此他的扩展性极差。

缺点:扩展性差。

注册功能

接受用户输入用户名,进行合法性校验,拿到合法的用户名

def check_username():
    username = input('username>>>').strip()
    if username.isalpha():
        return username
    else:
        print('用户名必须为字母')

接受用户输入密码,进行合法性校验,拿到合法的密码

def check_pwd():
    while True():
        pwd = input('password>>>').strip()
        if len(pwd) < 5:
            print('密码长度至少为五位')
            continue
        re_pwd = input('re_password>>>').strip()
        if pwd == re_pwd:
            return pwd
        else:
            print('两次输入密码不一致')

将合法的用户名和密码写入文件

def insert(username, pwd, path = '57.txt'):
    with open(path, 'a', encoding = 'utf8') as fa:
        fa.write(f'{username}:{pwd}\n')

注册

def register():
    username = check_username()
    pwd = check_pwd()
    insert(username, pwd)
    print(f'{username}注册成功')


register()

username>>>nick
password>>>12345
re_password>>>12345
nick注册成功

如果现在我们需要校验用户的年龄,因此我们需要增加一个check_age()方法,并且其他有牵连的地方都需要修改,因此它的扩展性极差。

封装文件读写功能

# def register():
#     while True:
#         username = input('username>>>').strip()
#         # 检测用户是否重复,如果重复则重新输入
#         with open('db.txt', 'r', encoding='utf8') as fr:
#             for line in fr:
#                 info = line.strip('\n').split(':')
#                 if username == info[0]:
#                     print('用户名已经存在')
#                     break
#             else:
#                 # 用户名不存在
#                 # 跳出循环,不用重复输入用户名字
#         res =

# def tell_info():
#     username = input('username>>>').strip()
#     with open('db.txt', 'r', encoding='utf8') as fr:
#         for line in fr:
#             info = line.strip('\n').split(':')
#             if username == info[0]:
#                 return info

数据处理层

def select(username):
    with open('db.txt', 'r', encoding='utf8') as fr:
        for line in fr:
            info = line.strip('\n').split(':')
            if username == info[0]:
                return info


def tell_info():
    username = input('username>>>').strip()
    info = select(username)
    print(info)

用户功能层

def register():
    while True:
        username = input('username>>>').strip()
        # 检测用户是否重复,如果重复则重新输入
        res = select(username)
        if res:
            print('用户名已经存在')
        else:
            break

    while True:
        pwd = input('password>>>').strip()
        re_pwd = input('re_password>>>').strip()
        if pwd != re_pwd:
            print('两次输入密码不一致,请重新输入')
        else:
            break

把注册功能分开之后,功能与功能直接解耦合,复杂的问题流程化,更加清晰。

分层实现功能

  • 用户功能层:实现用户具体的功能。
  • 接口层:连接数据处理层和用户功能层。
  • 数据处理层:处理数据后把结果交给接口层。

分层实现功能的好处:当我们需要实现web端和app端的软件,我们只要把数据处理层和接口层写好,然后实现不同的用户功能层即可,web端使用web端的用户功能层,app端使用app端的用户功能层,但是接口层和数据处理层是通用的。

转载于:https://www.cnblogs.com/huansan0209/p/11354517.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值