都是坑!!!

1.逻辑运算

print(1 > 2 and 3 or 5)

# 结果是:5
分析:
1>2 ----->False
False and 3 or 5 #  and 与0得0 

False or 5   # or 或1得1

则 结果为5

 2、自写一个列表的排序方法sort

li1 = [5, 6, 4, 3, 8]
# li1.sort()
# print(li1)  # [3, 4, 5, 5, 6, 8, 11]
def sort(args):
    li = []
    for item in range(len(li1)):
        j = 0
        for i in args:  # 此循环为了找到列表中的最大值
            if i > j:
                j = i
        args.remove(j)
        li.append(j)
    return li
print(sort(li1))

 3. 相互赋值

a = 1
b = 3
# 用一行代码将a,b的值互换
a, b = b, a
print(a, b)

4.元祖的坑

# 元组里面如果只有一个元素,且没有逗号,则该数据的数据类型与该元素相同
tu1 = ([1, 2, 3])
print(type(tu1))  # <class 'list'>
del tu1[0]  
print(tu1)  # [2, 3] 可以删除
tu2 = ([1, 2, 3],)
print(type(tu2))  # <class 'tuple'>  不可以删除

 5.python中for循环遍历时,注意不能对要遍历的对象进行增,删操作,否则会出现错误,列表不报错,字典报错.

# 删除列表中索引为奇数的元素
# 错误实例
li = [1, 2, 3, 4, 5]
for i in li:
    if li.index(i) % 2 == 1:
        li.remove(i)
print(li)

# 正确实例
li = [1, 2, 3, 4, 5]
li1 = li.copy()
for i in li:
    if li.index(i) % 2 == 1:
        li1.remove(i)
print(li1)

# 当然也以切片
li1 = li[::2]
# 还可以倒着删
li = [1, 2, 3, 4, 5]
for i in range(len(li)-1, -1, -1):
if i % 2 == 1:
li.pop(i)
print(li)
# 字典也一样
# dic = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3', 'name': 'alex'}
# dic1 = dic.copy()
# for i in dic:
#     if 'k' in i:
#         dic1.pop(i)
# print(dic1)

6.函数传可变类型时的坑

# 2,下面代码打印的结果分别是_________,________,________.


def extendList(val, list=[]):
    list.append(val)
    return list


list1 = extendList(10)  # 第一此未传入,使用的是为默认的list,此list是一个局部变量(可使用locals()查看)增加了值10,
                  但是注意list1是由函数把局部变量list,retun到全局变量中,赋值给list1,才是全局空间中开辟了一块内存,list1指向它;
list2 = extendList(123, []) # [123] 第二次使用的是自己传入的列表,增加了123,return给全局变量的list2 list3 = extendList('a') # 第三次调用函数,使用的是为默认的list,与第一次使用的list是同一个,公用一块内存,id号相同,都是第一次那个局部变量list,
                    但是这个局部变量随着函数的运行结束,本来应该释放掉,但是python的垃圾回收机制是:没那么快自动释放,
                    增加了值'a',此时内存中该list的值有10和'a',然后在把这块内存return给全局变量list3,此时list3也指向第一次的全局变量list1,
print('list1=%s' % list1) # 故结果为 list1=[10, 'a'] print('list2=%s' % list2) # list2=[123] print('list3=%s' % list3) # list3=[10, 'a'] list1,与 list3在全局空间中,指向同一块内存

7,注意:python不是内存级别的编程语言,python中的内存,打印出的id号,都是通过算法计算出来的类似内存地址id号;关于内存的,python在底层已经封装好了。 

8,局部变量与全部变量;

现象一:

 1 count = 2
 2 
 3 def test():
 4     print(count)       # 注意该print也报错
 5     count = count + 1  # 在函数内部如果有变量名和全局变量名相同且对该变量进行改变,
 6 #                        那么python会把你引用的变量视为局部定义的变量,但是局部没定义,                    # 要想不报错,加上golbal count
 7 #                        则count = count + 1会报错,第二个count未定义,
 8 #                        类似于赋值在运算a = a + 1,但是右边的a未定义
 9     print(count)
10 
11 test()                            

1 def test1():
2     count = 4
3     def test():
4         print(count)
5         count = 3 + count      # 和上述情况相同,也报错                     # 要想不报错,加上nonlocal count
 6 print(count) 7  test() 8 9 test1()

现象2:

1 def test2():
2     if tag:
3         print(666)
4     else:
5         global tag  # 函数体内,在利用global定义一个全局变量,或者修改一个全局变量之前,不能使用改变量
6         tag = True
7 
8 
9 test2()

 

 1 tag = True
 2 def test():
 3     if tag:
 4         print(tag)
 5     def test1():
 6         global tag  # 区别上面,这个是正确的,在嵌套函数的最上面
 7         tag = True
 8     test1()
 9 
10 test()
1 tag1 = True
2 while tag1:
3     print(666)
4     print(666)
5     tag1 = False  # 区别上面,for if while 没有开辟内存空间,原来在哪,for if while 后面的变量就在那,所以这里可以修改前,引用
6     print(666)

 9,列表表达式的坑

1、问题
有这么一个小面试题:

看下面代码请回答输出的结果是什么?为什么?

result = [lambda x: x + i for i in range(10)]
print(result[0](10))
2、解答
当你看到这篇文章的时候如果不知道这个知识点肯定会拿去直接运行,输出的结果是什么呢?

结果是:19

通过result[0~9](10)结果都是19就,懵逼了吧~~

想知道这个我们先看几个知识点

2.1、列表生成式
顾名思义,列表生成式就是一个用来生成列表的特定语法形式的表达式。

语法格式:

[expression for iterable_var in iterable]
工作过程:

迭代iterable的每个元素
把迭代的值赋值给iterable_var,然后通过expression的表达式进行计算得到一个新的值
最后把所有expression的值以新列表的形式返回
工作过程类似于:

L = []

for i in range(10):
    # 举例expression 表达式 iterable_var * 5 ,最后把这个结果加到列表中
    L.append(i * 5)  
点到为止,我们来看下我们的这个小面试题

复制代码
result = [lambda x: x + i for i in range(10)]
# 后面的lambada x:x +i 为expression 这是一个普通的lambada表达式那他生成的结果是什么? 一个一个的函数
# 看下面的例子就舒服多了
L = []

for i in range(10):
    L.append(lambda x: x + i)
复制代码
那在我们执行result[0](10),其实就是在执行lambda 10: 10 + i ,但是为什么每个i都是9呢?

2.2、函数内部变量的后期绑定(last binding)
我们在写一个函数的时候,函数内不保存这个变量的值,而是在执行的时候去找这个值在哪里绑定上的。

举个例子来说我们在函数中定引用了一个变量,可以不需要提前定义我们只要在使用前定义就可以了,如下面代码

def func():
    print(foo)

foo = "hello tim"

func()
注:这里有个点稍微提醒下,调用函数时这个函数必须是提前定义好的,这个我们称之为“前向引用”,而函数内部变量可以后期再定义,我们称之为“后期绑定”

因为这个变量不是在lambda内定义的,而是在列表生成式内定义的,我先把列表生成式翻译一下:

复制代码
def make_list():
    L =[]
    for i in range(10):
        def inner(arg):
            return i + arg
        L.append(inner)
    return L

result = make_list()
print(result[2](10))
复制代码
看上面的代码最后返回的都是一个一个的函数,而这个i的值是在循环的时候赋值的,那我们知道这个i的值不是在,inner(lambda)函数中定义的,而是引用的上层函数的变量,当我们使用inner去调用的时候,这时这个for循环已经结束了,i的值也就变成固定了9

所以每当我们通过函数lambda x: x + i 的时候这个i永远是9

2.3、小作修改
那如果说我不想要这样的结果,我想要i是循环的值怎么办,不要直接引用上层变量,把变量传进来就可以了

result = [lambda x, i=i, : x + i for i in range(10)]
print(result[1](10))
翻译一下

复制代码
def make_list():
    L =[]
    for i in range(10):
        def inner(arg, i=i):
            return i + arg
        L.append(inner)
    return L

result = make_list()
print(result[2](10))
复制代码
2.4、闭包
简单解释下这个概念,在嵌套函数内,嵌套函数应用上层函数的变量(不是全局变量)称之为闭包,

def func():
    x = 1

    def inner():
        print(x)
当我们执行func的时候就会生成一个闭包,func执行完后里面的变量x不会被回收,因为嵌套函数inner还在使用它,常见的应用场景就是我们的装饰器
很重要

 10,字典的key为什么不可变:字典的key在python中是通过算法计算的到的,要是可变,算法就不能精确计算出每一个key的位置了。

11,面向对象相关

什么时候运行
class A:
    def __init__(self):
        self.func()

    def func(self):
        print('in A')


class B(A):
    def func(self):
        print('in B')


B()  # in B  先找自己的init方法,没找到在去父类中找,注意在父类中找的时候,self还是B的实例,所以执行的是B类中的func
没有封装的
class A:
    def __init__(self):
        self.__func()  # 实际名称 _A__func 

    def __func(self):  # 函数在属性字典中是_A__func 名存的
        print('in A')


class B(A):
    def __func(self):  # 函数在属性字典中是_B__func 名存的
        print('in B')


B()  # in A # 找到父类中的init,再去执行self.__func(),时,实际上是现在自己的类中去找_A__func ,没找到,再去A类中找,找到了执行
类中进行封装

面式有东西: http://www.cnblogs.com/maple-shaw/articles/7648414.html

12 ,使用python,从一长串数字中找到重复多次的相邻的三个数字

num = '12332233332321234323123'
# num = 'abccbasdabcbbascsdxcasaabccac' 该方式也支持一段字母组成的字符串
#
res_lst = [num[i: i+3] for i in range(len(num))]

lst = []
count_lst = []
for i in res_lst:
    if len(i) == 3:
        if i not in lst:
            lst.append(i)

for item in lst:
    if res_lst.count(item) > 1:
        print(f"{item}出现的次数为{res_lst.count(item)}次")
seq = [0] * 1000  # 得到的是1000个0 组成的 大列表
for x in res_lst:
    seq[int(x)] += 1

for i in range(1000):
    if seq[i] > 1:
        print("{} repeat {} times".format(i, seq[i]))
方式二 只支持数字,不用count()内置方法

 13 台阶问题:

  上台阶,一次可以上一个台阶,可以上2个台阶,可以上3个台阶,问有n个台阶,有多少种走法?

def f(n):
    if n == 1:
        return 1
    if n == 2:
        return 2
    if n == 3:
        return 4
    return f(n-1) + f(n-2) + f(n-3)

 14 重新实现str.strip()

def right_strip(tempStr, splitStr):
    endindex = tempStr.rfind(splitStr)
    while endindex != -1 and endindex == len(tempStr) - 1:  
        # 和strip一样,对两边的字符才能做到去除的效果,所以这里需要判断,分割的字符是不是被分割字符串的两边的字符
        tempStr = tempStr[: endindex]
        endindex = tempStr.rfind(splitStr)  
        # 切完之后 继续循环,解决类似这种的两边是多个字符的(" sdfshhhh", "h"),可以把边上的h去光
    return tempStr


print(right_strip("sdfhhhs", "h"))


def left_strip(tempStr, splitStr):
    startindex = tempStr.find(splitStr)
    while startindex == 0:  # 只需要判断是切割字符串是 被切割字符串的最左边字符
        tempStr = tempStr[startindex+1:]
        startindex = tempStr.find(splitStr)
    return tempStr


print(left_strip(" h ", " "))

 

posted @ 2018-04-27 19:17  Mr.GLH  阅读(314)  评论(0)    收藏  举报
Top↑