面向对象
1、什么是面向对象?
i.面向对象和面向过程的区别
“面向过程”是一种是事件为中心的编程思想。就是分析出解决问题所需的步骤,然后用函数把这写步骤实现,并按顺序调用。
”面向对象“是以“对象”为中心的编程思想
面向过程:核心是过程二字,过程指的是解决问题的步骤,设计一条流水线,机械式的思维方式;优点:复杂的问题流程化,进而简单化;缺点:可扩展性差
面向对象:核心就是对象二字,对象就是特征与技能的结合体;优点:可扩展性强;缺点:编程复杂度高。
ii简述类、对象、实例化是什么?
一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型、模板。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法;
一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同;
实例化:把一个类转变为一个对象的过程就叫实例化
2、类与对象
i.实例和实例化
实例(对象):一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同;
实例化:把一个类转变为一个对象的过程就叫实例化。
ii.解释一下构造函数中__init__(self)中的self是什么意思?
self,就是实例本身!你实例化时python解释器会自动把这个实例本身通过self参数传进去。
iii.类变量和实例变量的区别和作用?
- 类变量:可在类的所有实例之间共享的值(也就是说,它们不是单独分配给每个实例的)。
- 实例变量:实例化之后,每个实例单独拥有的变量。实例变量:实例化之后,每个实例单独拥有的变量。
实例变量是某个对象的属性,只有实例化对象后,才会被分配空间,才能使用。类变量是所有对象共有,其中一个对象将它值改变,其他对象得到的就是改变后的结果;
而实例变量则属对象私有,某一个对象将其值改变,不影响其他对象;
3、继承和派生
class Parent(object): def __init__(self,name,age): self.name = name self.age = age class Child(Parent): def __init__(self,name,age,sex): Parent.__init__(self,name,age) #super.__init__(name,age) d = Child('ago',18,'M') print(d.name)
i. 以下python3代码最终结果是什么?也就是顺序是什么?继承广度优先和深度优先(继承的顺序)
class A(object): def test(self): print('A') class B(A): def test(self): print('B') class C(A): def test(self): print('C') class D(B): def test(self): print('D') class E(B): def test(self): print('E') class F(D,E,C): def test(self): print('F') f1 = F() f1.test() print(F.__mro__) #打印: F (<class '__main__.F'>, <class '__main__.D'>, <class '__main__.E'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
顺序是F--D--E--B--C--A--object
py3中继承的是广度优先
ii. 继承和装饰器
在定义类时,可以从已有的类继承, 被继承的类称为基类(父类),新定义的类称为派生类(子类)。
装饰器(deco):装饰函数的参数是被装饰的函数对象,返回原函数对象 装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象 概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
类装饰器:@property 装饰过的函数返回的不再是一个函数,而是一个property对象,装饰过后的方法不再是可调用的对象,可以看做数据属性直接访问。
@staticmethod (静态方法)把没有参数的函数装饰过后变成可被实例调用的函数, 函数定义时是没有参数的,可以不接收参数
@classmethod (类方法)把装饰过的方法变成一个classmethod类对象,既能被类调用又能被实例调用。 注意参数是cls代表这个类本身。 一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法。 而使用@staticmethod或@classmethod,就可以不需要实例化,直接类名.方法名()来调用。 这有利于组织代码,把某些应该属于某个类的函数给放到那个类里去,同时有利于命名空间的整洁。
iii. 继承和组合(把一个实例当成参数传给类)
通过继承建立了派生类与基类之间的关系,它是一种'是'的关系,比如白马是马,人是动物。
当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如老师是人,学生是人
用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python和linux课程,教授有学生s1、s2、s3
组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合。
4、属性和绑定方法
i. 共有属性和私有属性
_m:代表私有属性,仅能在实例的内部各方法(函数)中调用;隐藏一些功能的的实现细节,只给外部暴露调用。
共有属性是所有对象都可以用的
5、多态和多态性
多态指的是一类事物有多种形态。动物有多种形态:人,狗,猪等
多态性指在不考虑实例类型的情况下使用实例;多态性分为静态多态性和动态多态性。
静态多态性:如任何类型都可以用运算符+进行运算;字符串、列表、数字都能用上加上,站在+号的角度。
动态多态性:
#多态是同一种事物的多种形态 class Animal: def talk(self): print('正在叫') class People(Animal): def talk(self): print('say hello') class Pig(Animal): def talk(self): print('哼哼哼') class Dog(Animal): def talk(self): print('汪汪汪') class Cat(Animal): def talk(self): print('喵喵喵') peo1=People() pig1=Pig() dog1=Dog() cat1=Cat() #多态性 peo1.talk() dog1.talk() pig1.talk() def func(x): x.talk() func(peo1) func(pig1) func(dog1) func(cat1) #输出结果: # say hello # 汪汪汪 # 哼哼哼 # say hello # 哼哼哼 # 汪汪汪 # 喵喵喵
6、封装
封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需改变。
7、构造方法__init__和析构方法__del__
__init__()类的初始化,类被实例化的时候执行该函数,放置需要初始化的属性;
__del__()回收资源的,外部主动调用执行,对象在作用域中调用完毕,跳出作用域就会被执行、释放内存空间。
8、以下代码执行后分别得到结果是什么?说明缘由
class A: def __test(self): #_A__test print('A.test') def func(self): print('A.func') self.__test()#b._A__test() class B(A): def __test(self): #_B__test print('B.test') b = B() b.func() #打印: A.func A.test
实例化对象b先从自己这找func,没有再去自己的类里边找,也没有再去父类A里边找,得到A.func
self.__test()相当于是b._A__test();在A类中,__test(self)将其封装了,实际上是_A__test;在B类中,__test(self)相当于_B__test,所以是A.test
class A: def test(self): print('A.test') def func(self): print('A.func') self.test()#b.test() class B(A): def test(self): print('B.test') b = B() b.func() #打印: A.func B.test
实例化对象b先从自己这找func,没有再去自己的类里边找,也没有再去父类A里边找,得到A.func;self.test()相当于b.test()自己这没有,在自己的类B中找,得到B.test
- 特性property 有什么作用?name.setter和name.deleter
什么是property,如何定义,如何使用,给谁用,什么情况下应该将一个属性定义成
property,有什么好处?
property是把一个方法转换成实例的属性。func = property(func) 或者@property来装饰方法(函数)
此时的name是一个property对象。该对象下面有getter、setter、deleter等方法。
只有@property表示只读;同时有@property和@x.setter表示可读可写;同时有@property和@x.setter和@x.deleter表示可读可写可删除。
(参考:http://www.cnblogs.com/yangzhenwei123/p/6759311.html)
10、静态方法和类方法staticmethod和classmethod区别是什么?
class A: __role ='CHINA' #_A__role = 'CHINA' @classmethod #绑定到类的方法,由类来调用,把类当做第一个参数传进去 def show_role(cls): print(cls.__role) #A._A__role @staticmethod #非绑定方法,对象和类都可以调用,没有自动传值了 def get_role(): return A.__role # A._A__role @property #让使用者使用的时候感知不到他是个调用一个功能,他以为自己是用的数据属性。必须要有个返回值作为它的结果 def role(self): return self.__role #a._A__role a = A() print(a.role) print(a.get_role()) a.show_role() #打印: CHINA CHINA CHINA
__role在类中属于类的数据属性,被隐藏起来了,实际上是_A__role
三个装饰器的作用见上边代码。
11、反射
使用反射的知识点查看类的静态属性role;使用反射的知识点调用类的func方法;请为b对象设置一个name属性,值为你的名字。
class B: role = 'CHINA' def func(self): print('in func') b = B() print(getattr(B,'role')) getattr(b,'func')() setattr(b,'name','kris') print(b.name) #打印: CHINA in func kris
12、__getitem__ __delitem__ __setitem__ 的作用?
可以让对象变成一个dict一样操作;
13、利用type语法生成下面这个类
class Test(object): def __init__(self,name,age): self.name = name self.age = age def sayhi(self,name): print('self',name,self.name)
#类名
class_name = 'Test'
#类的父体
class_bases = (object,)
#类体
class_body ="""
def __init__(self,name,age): self.name = name self.age = age def sayhi(self,name): print('self',name,self.name) """ class_dic = {} exec(class_body,globals(),class_dic) Test = type(class_name,class_bases,class_dic) print(Test) #打印: <class '__main__.Test'>
14、__new__()作用是什么,它和__init__ 有什么关系?
__new__用来创建类对象,实例化一个cls的类对象,表示这个类已经被加载了,解析了,现在可以拿着这个类创建普通实例对象了。如果类对象创建失败,则不会调用init方法;其用处是:自定义方式创建类对象,比如改变这个类的属性等。
__new__ 用来创建实例,在返回的实例上执行__init__,如果不返回实例那么__init__将不会执行;实例化一个类时,最先被调用的方法 其实是 __new__ 方法
__init__是在类实例创建之后调用,而 __new__方法正是创建这个类实例的方法。
参考:http://www.jb51.net/article/48044.htm
15、自定义元类利用metaclass __new__ __init__ __call__创建一个类(定制类)
class MyType(type): def __init__(self, *args, **kwargs): print("元类init") super(MyType, self).__init__(*args, **kwargs) def __new__(cls, *args, **kwargs): print("new") return super().__new__(cls, *args, **kwargs) def __call__(self, *args, **kwargs): print("call") obj = self.__new__(self, *args, **kwargs) # object.__init__(....) obj.__init__(*args, **kwargs) # self.__init__(obj,*args, **kwargs) return obj ##没有这一步,结果也是一样的 class Foo(object, metaclass=MyType): def __init__(self): print('本类init') x = Foo() # new # 元类init # call # 本类init
16、自定义类
i. 一个圆形类,属性是半径,提供两个方法,计算圆周长和面积
from math import pi class Circle: def __init__(self,r): self.r = r def area(self): return self.r**2*pi def perimeter(self): return 2*pi*self.r c1 = Circle(5) print(c1.area()) print(c1.perimeter()) #打印: 78.53981633974483 31.41592653589793
ii. 实现如图的继承关系,然后验证经典类与新式类在查找一个属性时的搜索顺序
经典类是深度优先;新式类是广度优先的查找顺序
iii. 基于多态的概念来实现linux中一切皆问题的概念:文本文件,进程,磁盘都是文件,然后验证多态性
import abc class All_file(metaclass=abc.ABCMeta): @abc.abstractmethod def read(self): print('All file') pass @abc.abstractmethod def write(self): print('All file') pass class Text(All_file): def read(self): super().read() print('Text read') def write(self): super().write() print('Text write') class Sata(All_file): def read(self): super().read() print("Sata read") def write(self): super().write() print("Sata write") def read(obj): obj.read() def write(obj): obj.write() t = Text() s = Sata() t.read() s.write() read(s) #打印: All file Text read All file Sata write All file Sata read
iv. 定义老师类,把老师的属性:薪资,隐藏起来,然后针对该属性开放访问接口
class Teacher(): def __init__(self,name,sex,salary): self.name = name self.sex = sex self.__salary = salary def tell_salary(self): print('你的工资是%s'%self.__salary) t1 = Teacher('alex','male',10000) t1.tell_salary()
v. 定义如下类,并最大程度地重用代码(继承,派生:子类重用父类方法,组合)老师类 学生类 分数类 课程类 日期类
class People(): school = 'luffycity' def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex class Teacher(People): def __init__(self,name,age,sex,salary): super().__init__(name,age,sex) self.salary = salary def teach(self): print('%s is teaching'%self.name) class Student(People): def __init__(self,name,age,sex,class_time): super().__init__(name,age,sex) self.class_time = class_time def learn(self): print('%s is learning'%self.name) class Course: def __init__(self,course_name,course_price): self.course_name = course_name self.course_price = course_price def tell_info(self): print("课程名%s,课程价钱%s"%(self.course_name,self.course_price)) class Data: def __init__(self,year,month): self.year = year self.month = month def tell_info(self): print('%s年%s月'%(self.year,self.month)) tea1 = Teacher('alex',33,'male',10000) stu1 = Student('kris',22,'male',7) python = Course('python','8999') data1 = Data(2018,4) tea1.course = python print(python)
vi. 基于授权定制自己的列表类型,要求定制的自己的__init__方法
vii. 定制自己的append:只能向列表加入字符串类型的值
viii. 定制显示列表中间那个值的属性(提示:property)
ix. 其余方法都使用list默认的(提示:__getattr__加反射)
class List: def __init__(self,value): self.x=list(value) def append(self,value): if not isinstance(value,str): raise TypeError('append到列表的内的元素必须是str类型') self.x.append(value) def insert(self,index,value): self.x.insert(index,value) def __getattr__(self, item): return getattr(self.x,item) @property def type(self): print(self.x) t=int(len(self.x)/2) print(self.x[t],type(self.x[t])) l=List([1,2,3]) l.append("egon") l.append('hello') l.append('alex') l.insert(7,5) l.pop() l.type #打印 [1, 2, 3, 'egon', 'hello', 'alex'] egon <class 'str'>
x. 定义用户类,定义属性db,执行obj.db可以拿到用户数据结构
#user.db文件 { "egon":{"password":"123",'status':False,'timeout':0}, "alex":{"password":"456",'status':False,'timeout':0}, }
class User: db_path='user.db' def __init__(self,username): self.username=username @property def db(self): data=open(self.db_path,'r').read() return eval(data) u=User('egon') print(u.db['egon']) print(u.db['egon']['password']) #打印: {'password': '123', 'status': False, 'timeout': 0}
xii. 根据下述原理,编写退出登录方法(退出前判断是否是登录状态),自定义property,供用户查看自己账号的锁定时间
参考:http://www.cnblogs.com/DragonFire/p/6748082.html
import time class User: db_path='user.db' def __init__(self,name): self.name=name @property def db(self): with open(self.db_path,'r') as read_file: info=read_file.read() return eval(info) @db.setter def db(self,value): with open(self.db_path,'w') as write_file: write_file.write(str(value)) write_file.flush() def login(self): data=self.db if data[self.name]['status']: print('已登录') return True if data[self.name]['timeout'] < time.time(): count=0 while count < 3: passwd=input('password>>: ') if not passwd:continue if passwd == data[self.name]['password']: data[self.name]['status']=True data[self.name]['timeout']=0 self.db=data break count+=1 else: data[self.name]['timeout']=time.time()+10 self.db=data else: print('账号已锁定10秒') u1=User('egon') u1.login() u2=User('alex') u2.login()
网络编程
1、三次握手/四次挥手
基于tcp协议,客户端给服务端发一次消息,服务端要回应下并且给发给客户端,然后客户端再发给服务端,中间两步回应下+给客户端发消息可以合成一步,链接建立完成也就是三次握手;客户端说要断开链接PIN=1,服务端确认下ack=1,客户端接收到了,这条管道就断开了,服务端要断开发PIN=1,客户端回一个ack=1,管道就断开了。
客户端说把数据传完了,服务端不一定传完数据了,中间那两步不能合成一步,所以断开链接需要四次挥手。
2、osi七层模型
物理层功能:主要是基于电器特性发送高低电压(电信号),高电压对应数字1,低电压对应数字0。
数据链路层的功能:定义了电信号的分组方式按照以太网协议;一组电信号构成一个数据包,叫做一组数据‘帧’;每一数据帧分成:报头head和数据data两部分。head前六个字节和后六个字节是mac地址,基于mac地址来标示对方;在局域网内以广播的方式工作。
网络层功能:引入一套新的地址用来区分不同的广播域/子网,这套地址即网络地址。
传输层功能:建立端口到端口的通信,端口即应用程序与网卡关联的编号。tcp和udp
应用层功能:有自己的协议如http、ftp协议,跑应用软件。
3、ip
每台机器配个ip地址,有一个IP头和data数据。IP地址和mac地址就可以找到世界上一*一无二的机器。IP找到子网,mac找到子网它在哪个位置。
IP协议:
- 规定网络地址的协议叫ip协议,它定义的地址称之为ip地址,广泛采用的v4版本即ipv4,它规定网络地址由32位2进制表示
- 范围0.0.0.0-255.255.255.255
- 一个ip地址通常写成四段十进制数,例:172.16.10.1
4、socket 写一个简单的socket的服务端和客户端
##服务端 import socket ph = socket.socket(socket.AF_INET,socket.SOCK_STREAM) ph.bind(('127.0.0.1',8081)) ph.listen(5) print('starting') conn,client_addr = ph.accept() print(client_addr) while True: data = conn.recv(1024) conn.send(data.upper()) conn.close() ph.close() ###客户端 import socket ph = socket.socket(socket.AF_INET,socket.SOCK_STREAM) ph.connect(('127.0.0.1',8081)) while True: msg = input('>>>:') ph.send(msg.encode('utf-8')) data = ph.recv(1024) print(data) ph.close()
5、黏包,解释下黏包现象,如何解决。
客户端只recv(1024), 可结果比1024长只好在服务器端的IO缓冲区里把客户端还没收走的暂时存下来,等客户端下次再来收,所以当客户端第2次调用recv(1024)就会首先把上次没收完的数据先收下来,再收df命令的结果。 这个现象叫做粘包,就是指两次结果粘到一起了。它的发生主要是因为socket缓冲区导致的。问题的根源在于,接收端不知道发送端将要传送的字节流的长度,所以解决粘包的方法就是围绕,如何让发送端在发送数据前,把自己将要发送的字节流总大小让接收端知晓,然后接收端来一个死循环接收完所有数据。
服务端:1收命令;2执行命令,拿到结果;3把命令的结果返回给客户端:3.1制作固定长度的报头;3.2先发送报头的长度;3.3再发报头;3.4再发真实数据
客户端:1发命令;2拿到命令的结果并打印下;2.1先收报头的长度;2.2再收报头;2.3从报头中解析出对真实数据的描述信息;2.4接收真实数据。
报头:字典的形式里有文件名,状态码,文件大小等等
报头长度 struct
6、异常,自定义一个异常
try: print('--before---') l = [1,2,3] l[100] print('--->>>') except Exception as e: print('异常发生了:',e) print('after---')
#自定义个异常类型 class Myexception(BaseException): def __init__(self,msg): super(Myexception,self).__init__() self.msg = msg def __str__(self): return '<%s>'%self.msg raise Myexception('我自己的异常类型')
7、socket和socketserver的区别是什么?
socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。在Internet上的主机一 般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。
SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进 程” 专门负责处理当前客户端的所有请求。
8、写一个客户端调用服务端的系统命令的程序
import socket import subprocess phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.bind(('127.0.0.1',8081)) phone.listen(5) print('starting') while True: conn,client_addr = phone.accept() print(client_addr) while True: try: #1收命令 cmd = conn.recv(1024) #2执行命令拿到结果 obj = subprocess.Popen(cmd.decode('utf-8'),shell= True, stdout = subprocess.PIPE, stderr = subprocess.PIPE) stdout = obj.stdout.read() stderr = obj.stderr.read() #3把命令结果返回给客户端 print(len(stdout)+len(stderr)) conn.send(stdout+stderr) except ConnectionResetError: break conn.close() phone.close()
import socket import subprocess phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(('127.0.0.1',8081)) while True: #1发命令 cmd = input('>>>:').strip() if not cmd:continue phone.send(cmd.encode('utf-8')) #2拿命令结果并打印 data = phone.recv(1024) print(data.decode('gbk')) phone.close()
编程题
1.定义两个类(人)实例化出:老王和小明
i.共同属性及技能:出生地,吃饭
不同属性及技能:a.属性:名字,年龄;
b.老王技能1:讲课;
c.老王技能2:布置作业
d.小明技能1:罚站
e老王技能3:打小明(假设小明有100点血,被打之后就掉了50点血了)
使用到了继承:共同技能和属性
定义了老王的攻击力:50
定义了小明的血量:100
class Laowang(): bron = 'China' def __init__(self, name, age, hp, aggresivity): self.name = name self.age = age self.hp = hp self.aggresivity = aggresivity def eat(self): print("%s is eating"%self.name) def talk_lesson(self): print("%s is talking lesson"%self.name) def have_homework(self): print("%s could have_homework"%self.name) def attack(self,xm_obj): print('%s 打了%s'%(self.name,xm_obj.name)) xm_obj.hp -= self.aggresivity class Xiaoming: def __init__(self,name,age): self.name = name self.age = age self.hp = 100 def stand(self): print('%s is standing'%self.name) lw = Laowang('老王','32',80,50) xm = Xiaoming('小明',22) lw.attack(xm) print(xm.hp)
ii.模拟cs游戏
人物角色分为警察和匪徒两种,定义成两个类;所有的警察角色都是police;每个警察都有自己独有名字,生命值,武器,性别;每个人都可以开枪攻击敌人,且攻击目标不能是police;
所有的匪徒的角色都是terrorist;每个匪徒都有自己独有名字,生命值,武器,性别;每个人都可以开枪攻击别人,且攻击目标不是是terrorist;
a,实例化一个警察,一个匪徒,警察攻击匪徒,匪徒掉血
class Police(): def __init__(self,name,sex,hp,weapon,aggresivity): self.name = name self.sex = sex self.hp = hp self.weapon = weapon self.aggresivity = aggresivity def attack(self,terro_obj): print('%s attack %s'%(self.name,terro_obj.name)) terro_obj.hp -= self.aggresivity class Terrorist(Police): def __init__(self, name, sex, life_value, weapon, aggresivity): super().__init__( name, sex, life_value, weapon, aggresivity) def attack(self,poli_obj): print('%s attack %s'%(self.name,poli_obj.name)) poli_obj.hp -= self.aggresivity p1 = Police('laowang','male',100,'kk47',50) t1 = Terrorist('galen','female',100,'倚天剑',20) print(t1.hp) p1.attack(t1) print(t1.hp) t1.attack(p1) print(p1.hp)
综合题
1、远程执行命令(subprocess执行命令)
问答题(下面是一些答案参考)
简述什么是面向过程编程,优缺点以及应用场景
基于面向过程设计程序,就好比在设计一条流水线,是一种机械思维方法,核心是过程,过程就是解决问题的步骤,即先干什么,再干什么
优点:复杂的问题简单化
缺点:可扩展性差(牵一发而动全身)
应用场景:扩展性低的场合,如linux内核,httpd,git 简述什么是面向对象编程,优缺点以及应用场景
核心是对象,要理解对象应该把自己当成上帝,在上帝眼中一切存在的事物都是对象,不存 在也可以创建出来
优点:可扩展性强
缺点:无法像面向过程一样准确地知道什么阶段发生什么事,会有什么结果应用场景:与用户交互多的,公司内部的软件,游戏,互联网软件
简述什么是类和对象,可举例说明
特征与技能的结合体就是一个对象,在Python中,用变量表示特征,用函数表示技能 类是一系列对象共有的特征(变量的定义)与技能(函数的定义)的结合体
2、属性的引用,定义类会执行类体,生成名称空间
数据属性:Chinese.country ,如增删改查
函数属性:Chinese.talk('123'), 需要几个参数,就得传几个参数
3、实例化
p = Chinese('Linda') # 先调用类产生对象p,然后调用Chinese.init(p, 'Linda')
对象的使用:只有一种,就是属性引用
p.country
p.talk() # 会把p当做第一个参数传入self
4、简述类和对象的名称空间,以及查找顺序
类 :Chinese.dict对象:p.__dict__
对象使用属性时,先在自己对象的名称空间,再找所属类的名称空间简述什么是类的继承
继承是一种创建新类的方式,新建的类可以继承一个或多个父类, 父类又可称为基类或超类,新建的类称为派生类或子类
class ParentClass(object): pass
class SubClass(ParentClass): pass
print(SubClass.sbases)
5、简述什么是类的封装
封装数据的主要原因:保护隐私
封装方法的主要原因:隔离复杂度
6、简述什么是类的多态
同一种事物的多种形态,指的是父类
people_obj.talk()
pig_obj.talk()
dog_obj.talk()
def func(obj):
obj.talk()
好处:同一种调用方式,传入不同的对象,实现不同功能
7、简述什么是绑定方法和非绑定方法
在类内部定义的,只要没有装饰器,就是绑定到对象的方法,给对象用的,对象默认作为第 一个参数传入
在类内部定义的,有@classmethod装饰器,是绑定到类的方法,给类用的,类默认作为第一个参数传入
在类的定义定义的,有@staticmethod装饰器,就不是绑定方法了,不存在默认传值的间 题,定义几个参数,就传几个参数即可
8、简述什么是反射以及实现反射的方法
Python面向对象的反射:通过字符串的形式操作对象相关属性。Python中一切事物都是对象(都可以使用反射)
hasattr(object,name)
getattr(object, name, default=None) setattr(x, y, v)
delattr(x, y)
9、内置方法考核
isinstance和issubclass
1. isinstance字面意思:实列, 用户判断对象所属类型,包含类的继承关系.
class Person(object): pass obj = Person() a = isinstance(obj, Person) print(a) k1 = 10.0 k = isinstance(k1 ,int) print(k) k1 = 10 print(k)
2. issubclass字面理解:是子类. 用来判断类与类之间的关系, 含继承关系
class A: pass class B(A): pass b= B() print( isinstance(b,B)) 结果为True print( isinstance(b,A)) 结果为True print( issubclass(B,A)) 结果为True print( issubclass(B,object) 结果为True
setattr,delattr,getattr
setattr
(
object
, name, value):该函数给对象中的属性赋值,该属性若不存在,则会在对象里创建新的属性
delattr
(
object
, name):删除指定对象的属性,可以配合
hasattr
使用
getattr
(
object
, name[default]),
object
为对象名,name为对象属性(必须是字符串)
getattribute,getattr
getattr(self, item)定义当用户试图获取一个不存在的属性的行为
getattribute(self, item)定义该类的属性被访问时的行为
class C: def __getattr__(self, name): print(1) return super().__getattr__(name) def __getattribute__(self, name): print(2) return super().__getattribute__(name) def __setattr__(self, name, value): print(3) super().__setattr__(name, value) def __delattr__(self, name): print(4) super().__delattr__(name) c = C() c.x # 显示结果为 Traceback (most recent call last): 2 File "E:/Python Program/test.py", line 128, in <module> 1 c.x File "E:/Python Program/test.py", line 113, in __getattr__ return super().__getattr__(name) AttributeError: 'super' object has no attribute '__getattr__'
setitem,getitem,delitem
__setitem__:每当属性被赋值的时候都会调用该方法,因此不能再该方法内赋值 self.name = value 会死循环
__getitem__:当访问不存在的属性时会调用该方法
__delitem__:当删除属性时调用该方法
str,repr,format
str()
转化后的结果更适合与人进行交互,而repr()
转化后的结果则可以被Python
的解释器阅读
>>> s='hello world' >>> str(s) 'hello world' >>> repr(s) "'hello world'" >>>
>>> print('{} is a {}'.format('Cescfangs', 'gooner')) Cescfangs is a gooner
slots
__slots__ 由于Python是动态语言,任何实例在运行期都可以动态地添加属性。 如果要限制添加的属性,例如,Student类只允许添加 name、gender和score 这3个属性,就可以利用Python的一个特殊的__slots__来实现。 顾名思义,__slots__是指一个类允许的属性列表: class Student(object): __slots__ = ('name', 'gender', 'score') def __init__(self, name, gender, score): self.name = name self.gender = gender self.score = score 现在,对实例进行操作: >>> s = Student('Bob', 'male', 59) >>> s.name = 'Tim' # OK >>> s.score = 99 # OK >>> s.grade = 'A' Traceback (most recent call last): ... AttributeError: 'Student' object has no attribute 'grade' __slots__的目的是限制当前类所能拥有的属性,如果不需要添加任意动态的属性,使用__slots__也能节省内存。
next,iter
doc,module,class
__doc__ class Foo: '我是描述信息' pass print(Foo.__doc__) class Foo: '我是描述信息' pass class Bar(Foo): pass print(Bar.__doc__) #该属性无法继承给子类 该属性无法被继承
__module__ 表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
#!/usr/bin/env python # -*- coding:utf-8 -*- class C: def __init__(self): self.name = ‘SB' lib/aa.py lib/aa.py from lib.aa import C obj = C() print obj.__module__ # 输出 lib.aa,即:输出模块 print obj.__class__ # 输出 lib.aa.C,即:输出类
init,del
__init__
方法为类的初始化方法。当构造函数被调用的时候的任何参数都将会传给它。
__del__
它定义的是当一个对象进行垃圾回收时候的行为。
from os.path import join class FileObject: '''给文件对象进行包装从而确认在删除时文件流关闭''' def __init__(self, filepath='~', filename='sample.txt'): #读写模式打开一个文件 self.file = open(join(filepath, filename), 'r+') def __del__(self): self.file.close() del self.file
enter,exit
__enter__(self):当with开始运行的时候触发此方法的运行
__exit__(self, exc_type, exc_val, exc_tb):当with运行结束之后触发此方法的运行
简述什么是元类( 不做考核重点)
元类是类的类,是类的模板
元类是用来控制如何创建类的,正如类是创建对象的模板一样,而元类的主要目的是为了控 制类的创建行为
简述什么是异常以及语法
异常就是程序运行时发生错误的信号语法错误
逻辑错误
try...except
简述TCP/IP各层功能
物理层功能:主要是基千电器特性发送高低电压(电信号),高电压对应数字1,低电压对应数字0
数据链路层的功能:定义了电信号的分组方式
网络层功能:引入一套新的地址用来区分不同的广播域/子网,这套地址即网络地址传输层功能:建立端口到端口的通信
简述什么是Socket
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口简述
什么是黏包,黏包的原因是什么
问题的根源在于,接收端不知道发送端将要传送的字节流的长度, 所以解决粘包的方法就是围绕,如何让发送端在发送数据前,
把自己将要发送的字节流总大小让接收端知晓,然后接收端来一个死循环接收完所有数据
编程题
编写游戏角色交互
Garen,所属阵营Demacia,具有昵称,生命值200,攻击力100,具备攻击敌人技能Riven,所属阵营Noxus,具有昵称,生命值100,攻击力200,具备攻击敌人技能
交互:Garen对象攻击了Riven对象
class Hero: def __init__(self, name, hp, aggresivity): self.name = name self.hp = hp self.aggresivity = aggresivity def attack(self, enemy): enemy.hp -= self.aggresivity class Garan(Hero): camp = 'Demacia' def attack(self, enemy): super(Garan, self).attack(enemy) print('from garan') class Raren(Hero): camp = 'Noxus' g1 = Garan('草丛伦',100,30) r1 = Raren('瑞雯雯',80,50) g1.attack(r1) print('Raren',r1.hp) r1.attack(g1) print('Garan',g1.hp)
Socket的客户端服务端交互
客户端输入 hello 服务端将hello转换成 HELLO 然后发给客户端
import socket phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) phone.bind(('127.0.0.1', 8081)) print('server is running...') phone.listen(5) while True: conn, client = phone.accept() while True: try: data = conn.recv(1024) print(data.decode('utf-8')) conn.send(data.upper()) except Exception: break conn.close() phone.close()
import socket phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) phone.connect(('127.0.0.1', 8081)) while True: cmd = input('>>>:').strip() if not cmd:continue phone.send(cmd.encode('utf-8')) data = phone.recv(1024) print(data.decode('GBK')) phone.close()