1、面向对象三大特性,各有什么用处,说说你的理解。
封装(Encapsulation):在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法
继承(Inheritance):一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承
多态(Polymorphism):多态是面向对象的重要特性,简单点说:一种接口,多种实现,指一个基类中派生出不同的子类,且每个子类在继承了同样的方法
名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态
2、类的属性和对象的属性有什么区别?
类有两种属性:数据属性和函数属性
类的数据属性:是所有对象共享的
类的函数属性:是绑定给对象用的,称为绑定到对象的方法
对象的属性是类的实例化
3、面向过程编程与面向对象编程的区别与应用场景?
面向过程:
概念:核心是“过程”二字,“过程”指的是解决问题的步骤,即先干什么再干什么,基于面向过程设计程序就好比在设计一条流水线,是一种机械化的思维方式
优点是:
复杂的问题流程化,进而简单化
缺点是:
扩展性比较差
面向对象:
概念:核心是“对象”二字,
优点是:
可扩展性好
缺点是:
编程的复杂度比较高
应用场景:
需求经常变化的软件中
面向过程:个人视角
面向对象:上帝视角
4、类和对象在内存中是如何保存的。
类的对象的属性:以字典形式保存的
5、什么是绑定到对象的方法、绑定到类的方法、解除绑定的函数、如何定义,如何调用,给谁用?有什么特性
①、绑定到对象的方法:没有被任何装饰器装饰的方法
为对象量身定制
对象.boud_method(),自动将对象当作第一个参数传入
(属于类的函数,类可以调用,但是必须按照函数的规则来,没有自动传值那么一说)
由对象来调用,
def tell_info(self):
obj.tell_info()
②、绑定到类的方法:用classmethod 装饰器的方法
由类来调用
def from_conf(cls):
class.from_conf()
③、非绑定方法
不与类和对象绑定,谁都可以调用,没有自动传值
@staticmethod
def create_id():
obj.create_if()/class.create_id()
6、使用实例进行获取、设置、删除数据, 分别会触发类的什么私有方法
class A(object):
def __getitem__(self, item):
return self.__dict__.get(item)
def __delitem__(self, key):
del self.__dict__[key]
def __setitem__(self, key, value):
self.__dict__[key] = value
a = A()
a["key"] = "val"
print(a.__dict__)
# a = a["key"]
# print(a)
del a["key"]
print(a.__dict__)
7、python中经典类和新式类的区别
1.只有在Python2中才分新式类和经典类,Python3中统一都是新式类
2.在Python2中,没有显式的继承object类的类,以及该类的子类,都是经典类
3.在Python2中,显式的声明继承object的类,以及该类的子类,都是新式类
4.在Python3中,无论是否继承object,都默认继承object,即Python3中所有类都是新式类
当类是经典类时,按照:深度优先的方式查找
当类是新式类时,按照:广度优先的方式查找
8、如下示例, 请用面向对象的形式优化以下代码
def exc1(host, port, db, charset, sql):
conn = connect(host, port, db, charset)
conn.execute(sql)
return xxx
def exc2(host, port, db, charset, proc_name)
conn = connect(host, port, db, charset)
conn.call_proc(sql)
return xxx
# 每次调用都需要重复传入一堆参数
exc1('127.0.0.1', 3306, 'db1', 'utf8', 'select * from tb1;')
exc2('127.0.0.1', 3306, 'db1', 'utf8', '存储过程的名字')
class MySQLHandler:
def __init__(self, host, port, db, charset='utf-8'):
self.host = host
self.port = port
self.db = db
self.charset = charset
self.conn = connect(self.host, self.port, self.db, self.charset)
def exc1(self, sql):
return self.conn.execute(sql)
def exc2(self, sql):
return self.conn.call_proc(sql)
obj = MySQLHandler('127.0.0.1', 3306, 'db1')
obj.exc1('select * from tb1;')
obj.exc2('存储过程的名字')
9、请简单解释Python中staticmethod(静态方法)和 classmethod(类方法), 并分别补充代码执行下列方法。
staticmethod(静态方法):不与类和对象绑定,类和对象都可以调用,但是没有自动传值那么一说
classmethod(类方法):绑定到类的方法,是给类使用,类在使用时会将类本身当做参数传给类方法的第一个参数
10、下面这段代码的输出结果将是什么?请解释
class Parent(object):
x = 1
class Child1(Parent):
pass
class Child2(Parent):
pass
print(Parent.x, Child1.x, Child2.x)
Child1.x = 2
print(Parent.x, Child1.x, Child2.x)
Parent.x = 3
print(Parent.x, Child1.x, Child2.x)
# 1 1 1 继承自父类的类属性x,所以都一样,指向同一块内存地址
# 1 2 1 更改Child1,Child1的x指向了新的内存地址
# 3 2 3 更改Parent,Parent的x指向了新的内存地址
11、多重继承的执行顺序,请解答以下输出结果是什么?并解释。
class A(object):
def __init__(self):
print('A')
super(A, self).__init__()
class B(object):
def __init__(self):
print('B')
super(B, self).__init__()
class C(A):
def __init__(self):
print('C')
super(C, self).__init__()
class D(A):
def __init__(self):
print('D')
super(D, self).__init__()
class E(B, C):
def __init__(self):
print('E')
super(E, self).__init__()
class F(C, B, D):
def __init__(self):
print('F')
super(F, self).__init__()
class G(D, B):
def __init__(self):
print('G')
super(G, self).__init__()
if __name__ == '__main__':
g = G()
f = F()
输出:
G
D
A
B
F
C
B
D
A
12、请编写一段符合多态特性的代码
import abc
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod
def talk(self):
pass
class People(Animal):
def talk(self):
print('say hello')
13、请写一个小游戏,人狗大站,2 个角色,人和狗,游戏开始后,生成2个人,3条狗,互相混战,人被狗咬了会掉血,狗被人打了也掉血,狗和人的攻击力,具备的功能都不一样。
class Animal:
def __init__(self, name, life_value, gjl):
self.name = name
self.life_value = life_value
self.gjl = gjl
class People(Animal):
def attack(self, enemy):
if not isinstance(enemy, People):
enemy.life_value -= self.gjl
if enemy.life_value <= 0:
print("已经死亡")
else:
print("剩下的生命值为:", enemy.life_value)
print('人进行攻击')
else:
print('同类')
class Dog(Animal):
def attack(self, enemy):
if not isinstance(enemy, Dog):
enemy.life_value -= self.gjl
print(self.gjl)
if enemy.life_value <= 0:
print("已经死亡")
else:
print("剩下的生命值为:", enemy.life_value)
print('狗咬人')
else:
print('同类')
p1 = People('tom', 100, 30)
p2 = People('jack', 100, 50)
d1 = Dog('dog1', 100, 20)
d2 = Dog('dog2', 100, 30)
d1.attack(d2)
p1.attack(d2)
p2.attack(d2)
p1.attack(d2)
14、编写程序, 在元类中控制把自定义类的数据属性都变成大写.
class Mymetaclass(type):
def __new__(cls, name, bases, attrs):
update_attrs = {}
for k, v in attrs.items():
if not callable(v) and not k.startswith('__'):
update_attrs[k.upper()] = v
else:
update_attrs[k] = v
return type.__new__(cls, name, bases, update_attrs)
class Chinese(metaclass=Mymetaclass):
country = 'China'
tag = 'Legend of the Dragon' # 龙的传人
def walk(self):
print('%s is walking' % self.name)
print(Chinese.__dict__)
15、编写程序, 编写一个学生类, 要求有一个计数器的属性, 统计总共实例化了多少个学生.
class Student:
count = 0
def __init__(self, name, country, age):
self.name = name
self.country = country
self.age = age
Student.count += 1
s1 = Student('mike', 'china', 18)
s2 = Student('mike1', 'china', 18)
print(Student.count)
16、编写程序, 如下有三点要求:
自定义用户信息数据结构, 写入文件, 然后读取出内容, 利用json模块进行数据的序列化和反序列化
e.g
{
"egon": {"password": "123", 'status': False, 'timeout': 0},
"alex": {"password": "456", 'status': False, 'timeout': 0},
}
定义用户类,定义方法db,例如 执行obj.db可以拿到用户数据结构
在该类中实现登录、退出方法, 登录成功将状态(status) 修改为True, 退出将状态修改为False(退出要判断是否处于登录状态).密码输入错误三次将设置锁定时间(下次登录如果和当前时间比较大于10秒即不允许登录)
import json
import time
import os
user_dict = {
"egon": {"password": "123", 'status': False, 'timeout': 0},
"alex": {"password": "456", 'status': False, 'timeout': 0},
}
class User():
def __init__(self):
if not os.path.isfile('user.json'):
self.write()
def db(self):
with open('user.json', 'r', encoding='utf-8') as f:
return json.load(f)
def login(self):
count = 0
while count < 3:
username = input("请输入用户名:").strip()
password = input("请输入密码:").strip()
user_info = self.db()
if username in user_info.keys():
passwd = user_info.get(username).get("password")
time_o = user_info.get(username).get("timeout")
login_t = time.time()
print(username, login_t, time_o)
if login_t - time_o > 10:
if passwd == password:
print("欢迎登录,%s" % username)
user_info.get(username)["status"] = True
user_info.get(username)["timeout"] = time.time()
break
else:
print("用户名或密码错误!")
count += 1
else:
print("登录过于频繁,请间隔10秒再登录")
else:
print("用户名不存在!")
else:
print("错误次数大于三次")
user_info.get(username)["timeout"] = time.time()
self.save_user(user_info)
def exit(self, username):
user_info = self.db()
if username in user_info.keys():
if user_info.get(username)["status"]:
print("用户%s 已经登录,准备退出" % username)
time.sleep(3)
user_info.get(username)["status"] = False
self.save_user(user_info)
else:
print("用户名不存在!")
@staticmethod
def save_user(obj):
with open('user.json', 'r+', encoding='utf-8') as f:
json.dump(obj, f, ensure_ascii=False, indent=2)
@staticmethod
def write():
with open("user.json", "w", encoding="utf-8") as f:
json.dump(user_dict, f, ensure_ascii=False, indent=2)
login = User()
# login.write()
# print(login.db())
# login.login()
login.exit('egon')