面向对象的三大特性:
1.继承:解决代码的复用性问题
2.封装:对数据属性严格控制,隔离复杂度
3.多态性:增加程序的灵活性与可扩展性
首先需要理解这样一个概念:
Python中一切皆对象
因而‘类’也是一种对象
所以我们在谈论类的属性和对象的属性的区别时,实际上是在谈论‘类’这样一种特殊的对象与其他对象的区别。
类属性仅是与类相关的数据值,和普通对象属性不同,类属性和实例对象无关。这些值像静态成员那样被引用,即使在多次实例化中调用类,它们的值都保持不变。不管如何,静态成员不会因为实例而改变它们的值,除非实例中显式改变它们的值。
1.1 面向过程的程序设计
“面向过程”(Procedure Oriented)是一种以过程为中心的编程思想。“面向过程”也可称之为“面向记录”编程思想,不支持丰富的“面向对象”特性(比如继承、多态),并且它们不允许混合持久化状态和域逻辑。
•特点:分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了
•优点:复杂的问题流程化,进而简单化(一个复杂的问题,分成一个个小的步骤去实现,实现小的步骤将会非常简单)
•缺点:可扩展性差
•应用场景:面向过程的程序设计思想一般用于那些功能一旦实现之后就很少需要改变的场景, 如果你只是写一些简单的脚本,去做一些一次性任务,用面向过程的方式是极好的,著名的例子有Linux內核,git,以及Apache HTTP Server等。但如果你要处理的任务是复杂的,且需要不断迭代和维护 的, 那还是用面向对象最方便了。
1.2 面向对象的程序设计
“面向对象程序设计”(Object-oriented programming,缩写:OOP)是一种程序设计范型,同时也是一种程序开发的方法。对象指的是类的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。 面向对象程序设计可以看作一种在程序中包含各种独立而又互相调用的对象的思想,这与传统的思想刚好相反:传统的程序设计主张将程序看作一系列函数的集合,或者直接就是一系列对电脑下达的指令。面向对象程序设计中的每一个对象都应该能够接受数据、处理数据并将数据传达给其它对象,因此它们都可以被看作一个小型的“机器”,即对象。
•优点:可扩展性高
•缺点:编程的复杂度远高于面向过程,不了解面向对象而立即上手并基于它设计程序,极容易出现过度设计的问题,而且在一些扩展性要求低的场景使用面向对象会徒增编程难度,比如管理linux系统的shell脚本程序就不适合用面向对象去设计,面向过程反而更加适合。
•应用场景:面向对象程序设计推广了程序的灵活性和可维护性,并且在大型项目设计中广为应用。 此外,支持者声称面向对象程序设计要比以往的做法更加便于学习,因为它能够让人们更简单地设计并维护程序,使得程序更加便于分析、设计、理解。
类以及类中的方法在内存中只有一份,而根据类创建的每一个对象都在内存中需要存一份
根据类创建对象时,对象中除了封装 name 和 age 的值之外,还会保存一个类对象指针,该值指向当前对象的类。
当通过某对象执行其类中方法时,过程如下:
根据当前对象中的 类对象指针 找到类中的方法
将对象当作参数传给方法的第一个参数 self
def exc1(host,port,db,charset):
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 Exc:
host = '127.0.0.1'
port = 3306
db = 'db1'
charset = 'utf8'
conn = connect(host, port, db, charset)
def __init__(self, proc_name):
self.proc = proc_name
def test(self):
if self.proc =='select * from tb1;':
self.conn.execute(sql)
elif self.proc =='存储过程的名字':
self.conn.call_proc(sql)
return XXX
exc1 = Exc('select * from tb1;')
exc1.test()
exc2 = Exc('存储过程的名字')
exc2.test()
#从这里的优化结果可以看书,需要重复输入的内容变少了,但是类的代码量也不小
class People(object):
__name = "luffy"
__age = 18
p1 = People()
print(p1.__name, p1.__age)
#程序将会报错,因为隐藏属性不能直接被访问
print(p1._People__name, p1._People__age) #打印结果luffy 18
class People(object):
def __init__(self):
print("__init__")
def __new__(cls, *args, **kwargs):
print("__new__")
return object.__new__(cls, *args, **kwargs)
People()
__new__
__init__
#__new__方法接受的参数虽然也是和__init__一样,但__init__是在类实例创建之后调用,而 __new__方法正是创建这个类实例的方法。
class A(object):
def foo(self, x):
print("executing foo(%s, %s)" % (self,x))
@classmethod
def class_foo(cls, x):
print("executing class_foo(%s, %s)" % (cls,x))
@staticmethod
def static_foo(x):
print("executing static_foo(%s)" % (x))
a = A()
#classmehtod是给类用的,即绑定到类,类在使用时会将类本身当做参数传给类方法的第一个参数(即便是对象来调用也会将类当作第一个参数传入
#classmethod,绑定到类的方法
a.class_foo('绑定到类') #输出结果:executing class_foo(, 绑定到类)
A.class_foo('绑定到类') #输出结果:executing class_foo(, 绑定到类)
#在类内部用staticmethod装饰的函数即非绑定方法,就是普通函数,statimethod不与类或对象绑定,谁都可以调用,没有自动传值效果
#staticmethod 静态方法
a.static_foo('静态绑定') #输出结果:executing static_foo(静态绑定)
A.static_foo('静态绑定') #输出结果:executing static_foo(静态绑定)
class Dog(object):
def __init__(self,name):
self.name = name
@property
def eat(self):
print(" %s is eating" %self.name)
d = Dog("ChenRonghua")
d.eat()
d.eat()应该改为d.eat
@property使eat的接口发生了改变
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指向了新的内存地址
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
class Cat(Animal): #属于动物的另外一种形态:猫
def talk(self):
print('say miao')
def func(animal): #对于使用者来说,自己的代码根本无需改动
animal.talk()
cat1=Cat() #实例出一只猫
func(cat1) #甚至连调用方式也无需改变,就能调用猫的talk功能
#say miao
class Role(object):
def __init__(self,name):
self.name = name
def attack(self,enemy):
enemy.life_value-=self.agressivity
class People(Role):
agressivity = 10
life_value = 100
def __init__(self,name):
super().__init__(name)
class Dogs(Role):
agressivity = 15
life_value = 80
def __init__(self,name):
super().__init__(name)
p1 = People('Tom')
p2 = People('Jack')
d1 = Dogs('niker')
d2 = Dogs('geeker')
d3 = Dogs('chaox')
print(p1.agressivity)
print(p1.life_value)
p1.attack(d1)
print(d1.life_value)
class Student:
count = 0
@classmethod
def __init__(cls):
cls.count += 1
a1 = Student()
a2 = Student()
a3 = Student()
a4 = Student()
print(Student.count)
#输出4
class B:
def handle(self):
print('from B')
class A(B):
def handle(self):
super().handle()
a = A()
a.handle()
e.g
{
"egon":{"passwor":"123",'status':False,'timeout':0},
"alex":{"passwor":"456",'status':False,'timeout':0},
}
import json
eg={
"egon":{"passwor":"123",'status':False,'timeout':0},
"alex":{"passwor":"456",'status':False,'timeout':0},
}
with open('uesr_data.json', 'w', encoding='utf-8') as fp1:
json.dump(eg,fp1)
with open('uesr_data.json', 'r', encoding='utf-8') as fp2:
data = json.load(fp2)
print(data)
import json
class User:
@property
def db(self):
with open('uesr_data.json', 'r', encoding='utf-8') as fp:
data = json.load(fp)
return data
obj = User()
print(obj.db)
import json
import time
import pathlib
import os
import sys
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
print(base_dir)
sys.path.append(base_dir)
class User:
def __init__(self):
while True:
self.name = input('请输入用户名\n>>>:')
if not self.file_exist(base_dir):
print('输入的密码有误')
else:
break
self.data = self.db
def file_exist(self,path): # 通过判断指定路径下,以用户名命名的文件是否存在,来判断用户输入的用户正确
global file_path
file_name = 'db/%s.json' % self.name
file_path = os.path.join(path,file_name)
file_is = pathlib.Path(file_path)
file_result = file_is.is_file()
if file_result:
return file_path
else:
return False
@property
def db(self):
with open(file_path, 'r',encoding='utf-8') as file:
data = json.load(file)
return data
def login(self):
count = 0
while count < 3:
if self.data['timeout'] != 0:
if time.time() - self.db['timeout'] > 10:
print('不允许登录,时间超时!')
return False
with open(file_path,'r+',encoding='utf-8') as f:
count += 1
password = input('请输入密码\n>>>:')
if password != self.db['password']:
print('密码输入错误')
if count == 3:
self.data['timeout'] = time.time()
f.seek(0)
f.truncate()
json.dump(self.data, f)
continue
self.data['status'] = True
f.seek(0)
f.truncate()
json.dump(self.data,f)
print("--------welcome--------")
return True
def exit(self):
with open(file_path, 'r+', encoding="utf-8") as f:
data = json.load(f)
if data["status"]:
data["status"] = False
f.seek(0)
f.truncate()
json.dump(data, f)
else:
print("您现在处于退出状态")
user1 = User()
user1.login()
print(user1.__dict__)
user1.exit()