76.递归函数停止的条件?
递归的终止条件一般定义在递归函数内部,在递归调用前要做一个条件判断,根据判断的结果选择是继续调用自身,还是return;返回终止递归。
终止的条件:
1、判断递归的次数是否达到某一限定值
2、判断运算的结果是否达到某个范围等,根据设计的目的来选择
参考地址:https://blog.csdn.net/weixin_43527495/article/details/84841368
77.python写一个匿名函数求两个数的和
def sum(a,b): c=a+b return c if __name__=="__main__": print(sum(2,4)) a=lambda x,y: x+y print(a(1,2)) #使用匿名函数的实现方法
结果为:6,3
参考地址:https://www.cnblogs.com/wc554303896/p/7710974.html
设计模式
79.对设计模式的理解,简述你了解的设计模式?
设计模式是经过总结,优化的,对我们经常会碰到的一些编程问题的可重用解决方案。一个设计模式并不像一个类或一个库那样能够直接作用于我们的代码,反之,设计模式更为高级,它是一种必须在特定情形下实现的一种方法模板。 常见的是工厂模式和单例模式
81.单例模式的应用场景有那些?
单例模式应用的场景一般发现在以下条件下: 资源共享的情况下,避免由于资源操作时导致的性能或损耗等,如日志文件,应用配置。 控制资源的情况下,方便资源之间的互相通信。如线程池等,1,网站的计数器 2,应用配置 3.多线程池 4数据库配置 数据库连接池 5.应用程序的日志应用...
82.用一行代码生成[1,4,9,16,25,36,49,64,81,100]
print([x*x for x in range(1, 11)])
83.对装饰器的理解,并写出一个计时器记录方法执行性能的装饰器?
装饰器本质上是一个callable object ,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。
import time from functools import wraps def timeit(func): @wraps(func) def wrapper(*args, **kwargs): start = time.clock() ret = func(*args, **kwargs) end = time.clock() print('used:',end-start) return ret return wrapper @timeit def foo(): print('in foo()'foo())
84.解释以下什么是闭包?
在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包。
85.函数装饰器有什么作用?
装饰器本质上是一个callable object,它可以在让其他函数在不需要做任何代码的变动的前提下增加额外的功能。装饰器的返回值也是一个函数的对象,它经常用于有切面需求的场景。比如:插入日志,性能测试,事务处理,缓存。权限的校验等场景,有了装饰器就可以抽离出大量的与函数功能本身无关的雷同代码并发并继续使用。
86.生成器,迭代器的区别?
迭代器是遵循迭代协议的对象。用户可以使用 iter() 以从任何序列得到迭代器(如 list, tuple, dictionary, set 等)。另一个方法则是创建一个另一种形式的迭代器 —— generator 。要获取下一个元素,则使用成员函数 next()(Python 2)或函数 next() function (Python 3) 。当没有元素时,则引发 StopIteration 此例外。若要实现自己的迭代器,则只要实现 next()(Python 2)或 __next__
()( Python 3)
生成器(Generator),只是在需要返回数据的时候使用yield语句。每次next()被调用时,生成器会返回它脱离的位置(它记忆语句最后一次执行的位置和所有的数据值)
区别: 生成器能做到迭代器能做的所有事,而且因为自动创建iter()和next()方法,生成器显得特别简洁,而且生成器也是高效的,使用生成器表达式取代列表解析可以同时节省内存。除了创建和保存程序状态的自动方法,当发生器终结时,还会自动抛出StopIteration异常。
87.X是什么类型?
X= (i for i in range(10)) X是 generator类型
88.请用一行代码 实现将1-N 的整数列表以3为单位分组
N =100 print ([[x for x in range(1,100)] [i:i+3] for i in range(0,100,3)])
89.Python中yield的用法?
yield就是保存当前程序执行状态。你用for循环的时候,每次取一个元素的时候就会计算一次。用yield的函数叫generator,和iterator一样,它的好处是不用一次计算所有元素,而是用一次算一次,可以节省很多空间,generator每次计算需要上一次计算结果,所以用yield,否则一return,上次计算结果就没了
面向对象
90.Python中的可变对象和不可变对象?
什么是可变/不可变对象
-
不可变对象,该对象所指向的内存中的值不能被改变。当改变某个变量时候,由于其所指的值不能被改变,相当于把原来的值复制一份后再改变,这会开辟一个新的地址,变量再指向这个新的地址。
-
可变对象,该对象所指向的内存中的值可以被改变。变量(准确的说是引用)改变后,实际上是其所指的值直接发生改变,并没有发生复制行为,也没有开辟新的出地址,通俗点说就是原地改变。
Python中,数值类型(int
和float
)、字符串str、元组tuple都是不可变类型。而列表list、字典dict、集合set是可变类型。
参考地址:https://www.cnblogs.com/sun-haiyu/p/7096918.html
91.Python的魔法方法
参考地址:https://blog.csdn.net/qq_38520096/article/details/79237593
92.面向对象中怎么实现只读属性?
只读属性
1.概念:一个属性(一般指实例属性),只能读取,不能写入。
2.应用场景:有些属性,只限在内部根据不同场景进行修改,而对外界来说,不能修改,只能读取。
比如:电脑类的网速属性,网络状态属性
3.方式1:方案:全部隐藏(私有化,既不能读,也不能写。),部分公开(公开读的操作)
具体实现:私有化(通过“属性前置双下划线”实现。)部分公开:(通过公开的方法)
class Person: def __init__(self): self.__age = 18 def getAge(self): return self.__age p1 = Person() print(p1.getAge()) p1.__age = 99 print(p1.__age)
优化方案:装饰器@porperty。作用:将一些“属性的操作方法”关联到某一个属性当中。
class Person(object): def __init__(self): self.__age = 18 # 主要作用就是,可以以使用属性的方式,来使用这个方法。 @property def age(self): return self.__age p1 = Person() print(p1.age) p1.age = 1 print(p1.age)
概念补充:经典类:没有继承(object)
新式类:继承(object)
python2.x版本中定义一个类时,默认不继承(object)
python3.x版本中定义一个类时,默认继承(object)
建议使用:新式类
class Person: pass print(Person.__bases__) class Man: pass print(Man.__bases__) # 在python2.x版本中,如果定义一个类。没有显示的继承自object,那么这个类就是一个经典类。必须显示的继承自object,它才是一 # 个新式类 # 在python3.x版本中,如果直接定义一个类,会隐式的继承object,默认情况下,就已经是一个新式类。
class Person(object): # def __init__(self): # # self.__age = 18 # def get_age(self): # print("-----, getage") # return self.__age # # def set_age(self, value): # print("-----, setage") # self.__age = value # # age = property(get_age, set_age) # # p = Person() # # print(p.age) # # p.age = 90 # print(p.age) # print(p.__dict__)
5.property在新式类和经典类中的使用方法。
在经典类中使用property方法,只能关联读取方法。不能关联写入、删除这些方法。能写不能用。
#_*_encoding:utf-8_*_ # --------------------------------------------propert在新式类中的两种使用方法------------------------------------------- # property 第一种使用方式 # class Person(object): # def __init__(self): # # self.__age = 18 # def get_age(self): # print("-----, getage") # return self.__age # # def set_age(self, value): # print("-----, setage") # self.__age = value # # age = property(get_age, set_age) # # p = Person() # # print(p.age) # # p.age = 90 # print(p.age) # print(p.__dict__) # property 第二种使用方式 # class Person(object): # def __init__(self): # self.__age = 18 # @property # def age(self): # print("-----, get") # return self.__age # # @age.setter # def age(self, value): # print("-----, set") # self.__age = value # # # p = Person() # print(p.age) # # p.age = 100 # print(p.age) # --------------------------------------------propert在经典类中的两种使用方法------------------------------------------- # property 第在经典类中的第一种使用方式 # class Person(object): # def __init__(self): # self.__age = 18 # # def get_age(self): # print("-----, getage") # return self.__age # # def set_age(self, value): # print("-----, setage") # self.__age = value # # age = property(get_age, set_age) # # p = Person() # # print(p.age) # # p.age = 90 # print(p.age) # print(p.__dict__) # property 第在经典类中的第二种使用方式 class Person(object): def __init__(self): self.__age = 18 @property def age(self): print("-----, get") return self.__age @age.setter def age(self, value): print("-----, set") self.__age = value p = Person() print(p.age) p.age = 100 print(p.age) print(p.__dict__)
6.只读属性设置方式2
class Person(object): # 当我们通过实例.属性 = 值,给一个实例增加一个属性。或者说,修改一下属性的值的时候,都用调用这个方法。 # 在这个方法内部才会真正的把这个属性以及对应的数据,给存储到__dict__字典里面。 def __setattr__(self, key, value): print(key, value) #1. 判定key是否是我们要设置的只读属性的名称 if key == "age" and key in self.__dict__.keys(): print("这个属性是只读属性,不能设置数据") #2.如果说不是这个只读属性的名称,真正的添加到这个实例里面去。 else: self.__dict__[key] = value p1 = Person() p1.age = 18 print(p1.age) p1.age = 999 print(p1.age) p1.lala = 100 print(p1.lala) print(p1.__dict__)
参考地址:https://blog.csdn.net/u010962876/article/details/80740578
93.谈谈你对面向对象的理解?
所谓的面向对象就是将我们的程序模块化,对象化,把具体事物的特性属性和通过这些属性来实现一些动作的具体方法放到一个类里面,这就是封装。封装是我们所说的面相对象编程的特征之一。除此之外还有继承和多态。继承有点类似与我们生物学上的遗传,就是子类的一些特征是来源于父类的,儿子遗传了父亲或母亲的一些性格,或者相貌,又或者是运动天赋。有点种瓜得瓜种豆得豆的意思。面向对象里的继承也就是父类的相关的属性,可以被子类重复使用,子类不必再在自己的类里面重新定义一回,父类里有点我们只要拿过来用就好了。而对于自己类里面需要用到的新的属性和方法,子类就可以自己来扩展了。当然,会出现一些特殊情况,就是我们在有一些方法在父类已经定义好了,但是子类我们自己再用的时候,发现,其实,我们的虽然都是计算工资的,但是普通员工的工资计算方法跟经理的计算方法是不一样的,所以这个时候,我们就不能直接调用父类的这个计算工资的方法了。这个时候我们就需要用到面向对象的另一个特性,多态。对,就是多态,我们要在子类里面把父类里面定义计算工资的方法在子类里面重新实现一遍。多态包含了重载和重写。重写很简单就是把子类从父亲类里继承下来的方法重新写一遍,这样,父类里相同的方法就被覆盖了,当然啦,你还是可以通过super.CaculSalary方法来调用父类的工资计算方法。而重载就是类里面相同方法名,不同形参的情况,可以是形参类型不同或者形参个数不同,或者形参顺序不同,但是不能使返回值类型不同。
参考地址:https://blog.csdn.net/xukun5137/article/details/46792287