面试整理

发布于 / python / 0 条评论

1.and 和 or 的区别:

​ and:如果都为真值,就返回最后一个真值,如果都为假值,则返回第一个假值,不然返回真值

​ or:如果没有真值返回最后一个假值,如果都为真值返回第一个真值,不然返回假值

2.python递归的最大层数是1000层

3.三元运算符:值1 if 表达式 else 值2

a = 1 if True else 2

4.xrange 和 range的区别:

​ xrange返回一个生成器,而range是返回一个列表,将数据一次性加载到内存中,不适合很多数据

5.readlines:

​ 返回一个生成器

6.lambad表达式:


f = lambda x, y: x + y
print(f(2, 3))

7.pass的作用:

​ 占位语句,空语句,保证格式完整,保证语义完整

8.*args和**kwarg作用:

​ *args,传递多个参数,**kwargs传递多个类似于键值对的参数


def test(num, *args, **kwargs):
   print("num", end="")
   print(num)
   print("args", end="")
   print(args)
   print("kwargs", end="")
   print(kwargs)
test(2, 3, 4, 5, age=20, username="Tom")
num2
args(3, 4, 5)
kwargs{'age': 20, 'username': 'Tom'}

9.is和==的区别:

​ is比较的是地址,而==比较的是值

10.浅拷贝和深拷贝:

浅拷贝copy有两种情况:

第一种情况:复制的 对象中无 复杂 子对象,原来值的改变并不会影响浅复制的值,同时浅复制的值改变也并 不会影响原来的值。原来值的id值与浅复制原来的值不同。

第二种情况:复制的对象中有 复杂 子对象 (例如列表中的一个子元素是一个列表), 改变原来的值 中的复杂子对象的值  ,会影响浅复制的值。

深拷贝deepcopy:完全复制独立,包括内层列表和字典

11.垃圾回收机制:

​ ①引用计数:

Python垃圾回收主要以引用计数为主,分代回收为辅。引用计数法的原理是每个对象维护一个 ob_ref,用来记录当前对象被引用的次数,也就是来追踪到底有多少引用指向了这个对象,当发生以下四种情况的 时候,该对象的引用计数器+1

对象被创建  a=14对象被引用  b=a对象被作为参数,传到函数中   func(a)对象作为一个元素,存储在容器中   List={a,”a”,”b”,2}


// Python里面每一个东西都是对象,他们的核心是一个结构体Py_Object,所有Python对象的头部包含了这样一个结
//PyObject
struct _object {
   Py_ssize_t ob_refcnt;  # 引用计数值
   struct PyTypeObject *ob_type;
} PyObject;

​ ②标记清除:

​ ③分代回收:

12.可变类型和不可变类型:

​ 可变:集合,列表,字典

​ 不可变:数字,字符串,元组

13.python的常见内置函数:


数字有关:
abs(a) : 求取绝对值。abs(-1)  
max(list) : 求取list最大值。max([1,2,3])
min(list) : 求取list最小值。min([1,2,3])
sum(list) : 求取list元素的和。 sum([1,2,3]) >>> 6
sorted(list) : 排序,返回排序后的list。
len(list) : list长度,len([1,2,3])
divmod(a,b): 获取商和余数。 divmod(5,2) >>> (2,1)
pow(a,b) : 获取乘方数。pow(2,3) >>> 8
round(a,b) : 获取指定位数的小数。a代表浮点数,b代表要保留的位数。round(3.1415926,2) >>> 3.14
range(a[,b]) : 生成一个a到b的数组,左闭右开。 range(1,10) >>> [1,2,3,4,5,6,7,8,9]
 
 
功能有关:
eval() : 执行一个表达式,或字符串作为运算。 eval('1+1') >>> 2
exec() : 执行python语句。 exec('print("Python")') >>> Python
filter(func, iterable) : 通过判断函数fun,筛选符合条件的元素。 filter(lambda x: x>3, [1,2,3,4,5,6]) >>> <filter object at 0x0000000003813828>
map(func, *iterable) : 将func用于每个iterable对象。 map(lambda a,b: a+b, [1,2,3,4], [5,6,7]) >>> [6,8,10]
zip(*iterable) : 将iterable分组合并。返回一个zip对象。 list(zip([1,2,3],[4,5,6])) >>> [(1, 4), (2, 5), (3, 6)]
type():返回一个对象的类型。
id(): 返回一个对象的唯一标识值。
hash(object):返回一个对象的hash值,具有相同值的object具有相同的hash值。 hash('python') >>> 7070808359261009780
help():调用系统内置的帮助系统。
isinstance():判断一个对象是否为该类的一个实例。
issubclass():判断一个类是否为另一个类的子类。
globals() : 返回当前全局变量的字典。
next(iterator[, default]) : 接收一个迭代器,返回迭代器中的数值,如果设置了default,则当迭代器中的元素遍历后,输出default内容。
reversed(sequence) : 生成一个反转序列的迭代器。 reversed('abc') >>> ['c','b','a']
getattr(对象,属性) : 有则返回值,没则报错
setattr(对象,属性,值): 给对象赋值
hasattr(对象,属性):有则返回true,没有则返回false
python3里没有reduce,需要导入
# 举例
from functools import reduce
def add(x, y):
   return x + y
print(reduce(add, [1, 2, 3]))



map举例:
f = lambda x: x + 2
print(list(map(f, [1, 2, 3, 4])))      # 3,4,5,6

filter举例
def f(num):
   if num % 2 == 1:
       return num
result = list(filter(f, [2, 3, 4, 5, 6]))
print(result)      3,5

zip举例:
list1 = (1, 2, 3, 4)
list2 = ("a", "b", "c", "d")
result = zip(list1, list2)
print(list(result))    # [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]

14.字符串常用函数:


1,去掉空格和特殊符号
name = "lindong"
name.strip()  去掉空格和换行符
name.strip('xx')  去掉某个字符串
name.lstrip()  去掉左边的空格和换行符
name.rstrip()  去掉右边的空格和换行符
name.split()  默认是按照空格分割  返回列表
name.split(',')   按照逗号分割
[x:y:z]  x表示开头,y表示结尾,z表示步长
format 用法
name = "my name is {0} and i am {1} years old ".format("lindong", 12)
print(name)   # my name is lindong and i am 12 years old
‘,’.join(slit)      用逗号连接slit 变成一个字符串,slit 可以是字符,列表,字典(可迭代的对象)
name.ljust()  右边补充
name.rjust()  左边补充

15.列表常用函数


list.count()  # 计算某个元素出现的次数
list.append()  # 添加一个元素
list.extend() # 扩展一个元素
list.remove() # 移除列表中某个值的第一个匹配项(只会移出第一个)
list.insert(3, "test") # 将对象插入列表的第三个位置
list.reverse()  # 反向列表中元素

16.字典常用函数


增加:
dict_fruit["pineapple"] = “菠萝”
删除:
dict_fruit.pop["apple"]        #删除同时返回删除的值
dict_fruit.popitem()        #随机删除数组中的值
改:
dict_fruit["apple"] = "苹果1"
查找:
dict_fruit["apple"]        #如果值不存在报错
dict_fruit.get("apple")        #get 方法查找如果不存在返回空
dict_fruit.keys()        # 列出所有key 的值
dict_fruit.values()      # 列出所有value的值
dict_fruit.items()        #把key和value 放到元组里面
dict_fruit.update(res)    #把res字典填充到dict_update中有key的值覆盖  
"""
res = {"id": 1}
new_res = {"id": "lindong"}
res.update(new_res)
print(res)
"""
dict_fruit.setdefault(2,3)    #创建新的key 如果创建的key字典中有则返回原来key的值
dict.fromkeys(["a","b","c"],"xhl")        #批量生成相同value的字典

17.集合常用方法


s = set('hello')
print(s)
#结果是:
s = {'h', 'o', 'e', 'l'}
s.add(3)  # 添加元素
s.clear()  # 清空元素
s.discard(3)#指定删除,不存在该元素时不会报错
s.remove(3)#指定删除,不存在该元素时删除会报错

18.魔法方法


__new__(cls,*args):
   """
  1. __new__ 是在一个对象实例化的时候所调用的第一个方法
2. 它的第一个参数是这个类,其他的参数是用来直接传递给 __init__ 方法
3. __new__ 决定是否要使用该 __init__ 方法,因为 __new__ 可以调用其他类的构造方法或者直接返回别的 实例对象来作为本类的实例,如果 __new__ 没有返回实例对象,则 __init__ 不会被调用
4. __new__ 主要是用于继承一个不可变的类型比如一个 tuple 或者 string
  """
# 举例:
class Person(object):
   def __new__(cls, name, age):
       if 0 < age < 100:
           # return super(Person, cls).__new__(cls)
           return object.__new__(cls)
       else:
           return None

   def __init__(self, name, age):
       self.name = name
       self.age = age

p = Person("lindong", 20)
p1 = Person("linyue", 104)
print(p)
print(p1)
"""单例模式"""
class Singleton(object):
   __instance = None

   def __new__(cls, age, name):
       if not cls.__instance:
           cls.__instance = object.__new__(cls)
       return cls.__instance

   def __init__(self, age, name):
       self.age = age
       self.name = name
a = Singleton(12, "sad")
b = Singleton(13, "asdasd")
a.age = 20
print(b.age)



__del__(self)  # 摧毁实例

__str__(self)
# 举例
class B:
   def __init__(self, name):
       self.name = name

   def __str__(self):
       return self.name


t = B("lindong")
print(t)         # 返回__str__里的值


__repr__
# 作用类似于__str__,只不过在idle里,输入某个对象的实例,会输出

__getattr__(self, item): # 不存在该属性时,会调用此方法
__setattr__(self, name, value): # 所有的属性设置都会调用此方法,并且只有拥有这个魔法方法的对象才可以设置属性。使用这个方法要注意不要循环调用了
class TestClass:
   def __setattr__(self, name, value):
       print("执行__setattr__")
       object.__setattr__(self, name, value)

   def __init__(self,name):
       self.name = name

t=TestClass("Tom")
print(t.name)

__getattribute__   # 不管存不存在该属性都会调用

19.python多线程


"""
Thread和Threading:
  thread模块提供了基本的线程和锁定支持;而threading模块提供了更高级别、功能更全面的线程管理。
应该避免使用thread模块,尽量使用threading模块,原因如下:
(1)threading模块更加先进,有更好的线程支持,并且thread模块中的一些属性会和threading模块有冲突.
(2)thread模块拥有的同步原语很少,而threading模块有很多。
(3)thread模块对于进程何时退出没有控制。当主线程结束时,所有其他线程也都强制结束,不会发出警告或者进行适当的清理。
"""

# -*- coding:utf-8 -*-
# author: ld
import threading
import time
g_num = 0
def test1():
   global g_num
   for i in range(1000000):
       # mutex.acquire() # 上锁,如果未锁 成功否则堵塞
       g_num += 1
       # mutex.release() # 解锁
   print("test1=%d" % g_num)
def test2():
   global g_num
   for i in range(1000000):
       # mutex.acquire()
       g_num += 1
   # mutex.release()
   print("test2=%d" % g_num)
mutex = threading.Lock()  # 创建互斥锁,默认没有上锁
def main():
   t1 = threading.Thread(target=test1)
   t2 = threading.Thread(target=test2)
   t1.start()
   t2.start()
   time.sleep(6)
   print("main=%d" % g_num)
if __name__ == '__main__':
   main()

# 如果不上锁那么就会最后的值加的不对


# -*- coding:utf-8 -*-
# author: ld
import threading
import time


# 大致思路
# 获取对方的锁,运行一次后,释放自己的锁
def show1():
   for i in range(1, 52, 2):
       lock_show2.acquire()
       print(i, end='')
       print(i + 1, end='')
       time.sleep(0.2)
       lock_show1.release()


def show2():
   for i in range(26):
       lock_show1.acquire()
       print(chr(i + ord('A')))
       time.sleep(0.2)
       lock_show2.release()


lock_show1 = threading.Lock()
lock_show2 = threading.Lock()

show1_thread = threading.Thread(target=show1)
show2_thread = threading.Thread(target=show2)

lock_show1.acquire()  # 因为线程执行顺序是无序的,保证show1()先执行 获得了就
# 说明,被拿到了想再获得他的就无法获得,除非释放

show1_thread.start()
show2_thread.start()

# 获取对方的锁意味着那个代码被停止
# 释放自己的锁以为着对方可以拿到自己的锁

20.python多进程

进程: 一个运行的程序(代码)就是一个进程,没有运行的代码叫程序,进程是系统资源分配的最小单位,进程拥有自己独立的内存空间,所以进程间数据不共享,开销大.


# 举例
import time
import multiprocessing
def test1():
   while True:
       print("1--------")
       time.sleep(1)
def test2():
   while True:
       print("2--------")
       time.sleep(1)
def main():
   p1 = multiprocessing.Process(target=test1)
   p2 = multiprocessing.Process(target=test2)
   p1.start()
   p2.start()
if __name__ == '__main__':
   main()

   
   
# 进程池
import multiprocessing
import time
import os
import random
def test1(msg):
   t_start = time.time()
   print("%s开始执行,进程号为%d" % (msg, os.getpid()))
   time.sleep(random.random() * 2)
   t_stop = time.time()
   print("%s执行完成,耗时%.2f" % (msg, t_stop - t_start))
if __name__ == "__main__":
   po = multiprocessing.Pool(3)
   for i in range(0, 10):
       # Pool().apply_async(要调用的目标,(传递给目标的参数元祖,))
       # 每次循环将会用空闲出来的子进程去调用目标
       po.apply_async(test1, (i,))

   print("-----start-----")
   po.close()  # 关闭进程池,关闭后po不再接收新的请求
   po.join()  # 等待po中所有子进程执行完成,必须放在close语句之后
   print("-----end-----")
   

GIL锁:为了保证线程安全而采取的独立线程运行的限制

python由于有GIL锁,导致每一个进程执行时只有一个线程现在运行,所以python的多线程并不是真正的多线程,python的多线程适合I/O密集型操作,而多进程适合CPU密集型操作

​ 同步: 多个任务之间有先后顺序执行,一个执行完下个才能执行.

​ 异步:多个任务之间没有先后顺序,可以同时执行 有时候一个任务可能在必要的时候获取另一个同时执行的任务的结果,这就叫回调!

​ 阻塞: 如果卡住了调用者,调用者不能继续往下执行,就是说调用者阻塞了

​ 非阻塞:如果不会卡住, 可以继续执行,就是说非阻塞的

​ 同步异步相对于多任务而言,阻塞非阻塞相对于代码执行而言

并行: 同一时刻多个任务同时在运行.

并发:在同一时间间隔内多个任务都在运行, 但是并不会在同一时刻同时运行, 存在交替执行的情况

实现并行的库有: multiprocessing

实现并发的库有:threading

21.协程


# 迭代器
class Classmate:
   def __init__(self):
       self.names = list()
       self.current_num = 0

   def add(self, name):
       self.names.append(name)

   def __iter__(self):       # 得实现__iter__和__next__方法
       return self

   def __next__(self):
       if self.current_num < len(self.names):
           ret = self.names[self.current_num]
           self.current_num += 1
           return ret
       else:
           raise StopIteration
classmate = Classmate()
classmate.add("ld")
classmate.add("sr")
for item in classmate:
   print(item)

   
   
# 生成器
def create_num(number):
   a, b = 0, 1
   current_number = 0
   while current_number < number:
       ret = yield a  # 如果一个函数中有yield,那么这个函数就不是函数,是生成器
       print("=========", ret)
       a, b = b, a + b
       current_number += 1
   return "结束啦"


# 不是调用函数,而是创建生成器
obj = create_num(10)

while True:
   try:
       ret = next(obj)
       print(ret)
       obj.send("haha")
   except Exception as ret:
       print(ret)  # 获得return 的值
       break

22.进程,协程,线程

进程:

1、操作系统进行资源分配和调度的基本单位,多个进程之间相互独立

2、稳定性好,如果一个进程崩溃,不影响其他进程,但是进程消耗资源大,开启的进程数量有限制

线程:

1、CPU进行资源分配和调度的基本单位,线程是进程的一部分,是比进程更小的能独立运行的基本单位,一个进程下的多个线程可以共享该进程的所有资源

2、如果IO操作密集,则可以多线程运行效率高,缺点是如果一个线程崩溃,都会造成进程的崩溃

应用:

IO密集的用多线程,在用户输入,sleep 时候,可以切换到其他线程执行,减少等待的时间

CPU密集的用多进程,因为假如IO操作少,用多线程的话,因为线程共享一个全局解释器锁,当前运行的线程会霸占GIL,其他线程没有GIL,就不能充分利用多核CPU的优势

三、什么是协程协程是一种用户态的轻量级线程,又称微线程,英文名Coroutine,协程的调度完全由用户控制。人们通常将协程和子程序(函数)比较着理解。子程序调用总是一个入口,一次返回,一旦退出即完成了子程序的执行。协程的起始处是第一个入口点,在协程里,返回点之后是接下来的入口点。在python中,协程可以通过yield来调用其它协程。通过yield方式转移执行权的协程之间不是调用者与被调用者的关系,而是彼此对称、平等的,通过相互协作共同完成任务。其运行的大致流程如下:第一步,协程A开始执行。第二步,协程A执行到一半,进入暂停,通过yield命令将执行权转移到协程B。第三步,(一段时间后)协程B交还执行权。第四步,协程A恢复执行。

协程的特点在于是一个线程执行,与多线程相比,其优势体现在:

  • 协程的执行效率非常高。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。
  • 协程不需要多线程的锁机制。在协程中控制共享资源不加锁,只需要判断状态就好了。Tips:利用多核CPU最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能。

四、进程和线程的关系进程就像地主,有土地(系统资源),线程就像佃户(线程,执行种地流程)。每个地主(进程)只要有一个干活的佃户(线程)。进程-资源分配的最小单位,相对健壮,崩溃一般不影响其他进程,但是切换进程时耗费资源,效率差些。线程-程序执行的最小单位,没有独立的地址空间,一个线程死掉可能整个进程就死掉,但是节省资源,切换效率高。23.装饰器


# -*- coding:utf-8 -*-
# coding=utf-8

import time


# 无参数
def decorator(func):
   def wrapper():
       print(time.time())
       func()
   return wrapper


@decorator
def f1():
   print("this is a function")


f1()


# 有参数
def decorator(func):
   def wrapper(*args):
       print(time.time())
       func(*args)
   return wrapper


@decorator
def f2(func_name):
   print("this is a function", func_name)


f2("name")

24.闭包函数


def outer(num):
   def inner(num_2):
       return num + num_2
   return inner
a = outer(5)
b = a(2)
print(b)                        # 7

24.mysql

事务具有原子性,一致性,隔离性,持久性

索引:

​ 唯一索引,主键索引,聚集索引,非聚集索引

索引的优缺点:

​ 加快数据库的检索速度

​ 确保每一行数据的唯一性

​ 降低了插入,删除,修改的速度(这些操作会导致索引更新)

​ 索引需要占物理和数据空间

乐观锁:假设不会发生冲突,只有在提交时才会检查数据的完整性

悲观锁:假设会发生冲突,屏蔽一切可能破坏数据完整性的操作

存储引擎:

​ Innodb:支持事务,支持外键,而MYSIA不支持

​ 两种存储引擎所使用的索引的数据机构都是B+树

mysql的优化:

​ 1.select避免使用*号

​ 2.用truncae代替delete

​ 3.多使用内部函数

​ 4.使用表或者列的别名

​ 5.善用索引

​ 6.用IN代替OR


"""
Hash索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像BTree索引需要从根节点到枝节点,最后才能访问到叶节点这样多次的I/O访问,所以Hash索引的查询效率要远高于BTree索引。

可能很多人又有疑问了,既然Hash索引的效率要比BTree高很多,为什么大家不都用Hash索引而还要使用BTree索引呢?任何事物都是有两面性的,Hash索引也一样,虽然Hash索引效率高,但是Hash索引本身由于其特殊性也带了很多弊端和限制,主要有以下这些:

(1)Hash索引仅仅能满足"IN","="和"<=>"查询,你能使用范围查询。由于Hash索引比较的是进行Hash运算之后的Hash值,所以只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的Hash算法处理之后的Hash值的大小关系,并不能保证和Hash运算前完全一样。

(2)Hash索引无法被用来避免数据的排序操作。由于Hash索引中存放的是经过Hash计算之后的Hash值,而且Hash值的大小关系并不一定和Hash运算前的键值完全一样,所以数据库无法利用索引的数据来避免任何排序运算。

(3)Hash索引不能利用部分索引键查询。对于组合索引,Hash索引在计算Hash值的时候是组合索引键合并后再一起计算Hash值,而不是单独计算Hash值,索引通过组合索引的前面一个或几个索引键进行查询的时候,Hash索引也无法被利用。

(4)Hash索引在任何时候都不能避免表扫描。前面已经知道,Hash索引键是将索引键通过Hash运算之后,将Hash运算结果的Hash值和所对应的行指针信息存放于一个Hash表中,由于不同索引键存在相同Hash值,所以即使取满足某个Hash键值的数据的记录条数,也无法从Hash索引中直接完成查询,还是要通过访问表的实际数据进行相应的比较,并得到相应的结果。

(5)Hash索引遇到大量Hash值相等的情况后性能并不一定就会比BTree索引高。对于选择性比较低的索引键,如果创建Hash索引,那么将会存在大量记录指针信息与同一个Hash值相关联。这样要定位某一条记录时就会非常麻烦,会浪费多次表数据的访问,而造成性能低下。
"""

25.Redis

​ 五种数据类型:字符串,列表,集合,散列表,有序集合

​ 持久化 RDB 和 AOF

Redis快的主要原因是:

  • 完全基于内存
  • 数据结构简单,对数据操作也简单
  • 使用多路 I/O 复用模型
  • 单进程单线程好处
    • 代码更清晰,处理逻辑更简单
    • 不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗
    • 不存在多进程或者多线程导致的切换而消耗CPU

26.三次握手和四次挥手

第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

四次挥手过程第一次挥手:A数据传输完毕需要断开连接,A的应用进程向其TCP发出连接释放报文段(FIN = 1,序号seq = u),并停止再发送数据,主动关闭TCP连接,进入FIN-WAIT-1状态,等待B的确认。

第二次挥手:B收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v),B进入CLOSE-WAIT关闭等待状态,此时的TCP处于半关闭状态,A到B的连接释放。而A收到B的确认后,进入FIN-WAIT-2状态,等待B发出的连接释放报文段。

第三次挥手:当B数据传输完毕后,B发出连接释放报文段(FIN = 1,ACK = 1,序号seq = w,确认号ack=u+1),B进入LAST-ACK(最后确认)状态,等待A 的最后确认。

第四次挥手:A收到B的连接释放报文段后,对此发出确认报文段(ACK = 1,seq=u+1,ack=w+1),A进入TIME-WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,A才进入CLOSE状态。

27.re.compile是将正则表达式编译成一个对象,加快速度,并重复使用

28.sort和sorted区别

sort会将原列表排序,而sorted则是返回一个新的排序好的列表

29.编码和解码

编码:把码位转换成字节序列(通俗来说:把字符串转换成用于存储或传输的字节序列,python中是.encode())

解码:把字节序列转换成码位(通俗来说:把字节序列转换成人类可读的文本字符串,python中是.decode())

30.单下划线,双下划线

  • 使用单下划线(_one_underline)开头表示方法不是API的一部分,不要直接访问(虽然语法上访问也没有什么问题)。
  • 使用双下划线开头(__two_underlines)开头表示子类不能覆写该方法。除非你真的知道你在干什么,否则不要使用这种方式。
  • 当你想让自己定义的对象也可以像Python内置的对象一样使用Python内置的一些函数或操作符(比如len、add、+、-、==等)时,你可以定义该类方法。
  • 当然还有些属性只在末尾加了但下划线,这仅仅是为了避免我们起的一些名字和Python保留关键字冲突,没有特殊含义

31.继承

class A:
    def __init__(self, name):
        self.name = name


    def method(self):
        print("myname")
        print(self.name)


class B(A):
    def __init__(self, name, age):
        self.age = age
        # super().__init__(name)
        # super(B,self).__init__(name)
        A.__init__(self, name)

    def method(self):
        super().method()
        super(B,self).method()
        print("age")
        print(self.age)


b = B("linong", 20)
b.method()
# super(B,b).method()
super(B, b).method()
转载原创文章请注明,转载自: ت » 面试整理
Not Comment Found