Python学习之旅 —— 基础篇(八)面向对象、有序字典、设计模式之单例模式
概述
- 面向过程:根据业务逻辑从上到下写垒代码
- 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
- 面向对象:对函数进行分类和封装,让开发“更快更好更强...”
对比示例:函数式变成和面向对象编程
连接数据库的增删改查
# 函数式编程 def slect(host, username, password, sql): pass def create(host, username, password, database): pass def remove(host, username, password, table): pass def modify(host, username, password, nid): pass # 调用函数 hostname = "db01.renrenche.com" user = "admin" pwd = "123" slect(hostname, user, pwd, "select * from db1") create(hostname, user, pwd, "db1") remove(hostname, user, pwd, "table1") modify(hostname, user, pwd, "id01")
# 面向对象编程 # 01 创建类 class SQLHeper: def slect(self, sql): print(self.hostname) print(sql) def create(self, database): pass def remove(self, table): pass def modify(self, nid): pass # 02 创建对象 obj = SQLHeper() # 03 定义公共参数 obj.hostname = "db01.renrenche.com" obj.user = "admin" obj.pwd = "123" # 04 调用类的方法 obj.slect("select * from db1") obj.create("db1") obj.remove("table1") obj.modify("id")
一、创建类和对象
面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用。
类就是一个模板,模板里可以包含多个函数,函数里实现一些功能
对象则是根据模板创建的实例,通过实例对象可以执行类中的函数
- class是关键字,表示类
- 创建对象,类名称后加括号即可
二、面向对象的三大特性:
面向对象的三大特性是指:封装、继承和多态。
1、封装
引入__init__()方法:
# 01 创建类
class SQLHeper:
def __init__(self, host, username, password):
self.hostname = host
self.user = username
self.pwd = password
def slect(self, sql):
print(self.hostname)
print(sql)
def create(self, database):
pass
def remove(self, table):
pass
def modify(self, nid):
pass
# 02 创建对象
obj1 = SQLHeper("test1.rrc.com", "admin01", "123", )
obj2 = SQLHeper("test2.rrc.com", "admin02", "456", )
# 03 调用类的方法
obj1.slect("select * from db1")
obj2.slect("select count(*) from db2")
不止可以封装普通参数,可以封装任何参数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 类的对象可以封装任何参数 class c1: def __init__(self, name, obj): self.name = name self.obj1 = obj class c2: def __init__(self, job, age): self.job = job self.age = age def show(self): print(self.job) class c3: def __init__(self, aaa): self.abc = aaa c2_obj = c2("IT", 18) c1_obj = c1("Pesen", c2_obj) print(c1_obj.obj1.age) c3_obj = c3(c1_obj) # 通过c3 调用c2的show方法 c3_obj.abc.obj1.show()
2、继承
继承,面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容。
对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。
class Foo1: # Foo1是Foo2的父类(基类) def show(self, name): print("F1.show", name) class Foo2(Foo1): # Foo2是Foo1的子类(派生类) def __init__(self, name): self.name = name def bar(self): print("bar") def show(self, name): print("F2.show", name) obj = Foo2("aaa") obj.bar() obj.show("Pesen") # 优先执行自己的方法
python有一个特殊的继承方式就是多继承
3. 多态(多种形态、多种类型)
# python
def func(args): print(args) func(1) func("Pesen") func([0, 1, 2, 3, ])
# C#/java def func(int arg): print(arg) func(111) func("Pesen") # 报错
class A: pass class B(A): pass class C(A): pass # arg参数:必须是A类型或A的子类型 def (A arg): print(arg) obj1 = B() obj2 = C() obj3 = A() func(obj)
三、类成员(字段、方法、属性)
注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段。而其他的成员,则都是保存在类中,即:无论对象的多少,在内存中只创建一份。
1、字段
字段包括普通字段和静态字段。
- 普通字段:属于对象,在每个对象中都要保存一份
- 静态字段:属于类,在内存中只保存一份
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Province: country = "China" # 静态字段 def __init__(self, name): self.name = name # 普通字段 bj = Province("北京") # 一般情况下,自己访问自己的字段 # 规则: # 普通字段只能用对象访问 # 静态字段用类访问(万不得已的时候可以使用对象访问) print(bj.name) print(Province.country)
应用场景: 通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段
2、方法
方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。
- 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self;
- 类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;
- 静态方法:由类调用;无默认参数。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # Author:Pengcheng Xie class Province: country = "China" # 静态字段 def __init__(self, name): self.name = name # 普通字段 # 普通方法 def show(self): print(self.name) # 类方法 @classmethod def class_func(cls): print(cls.country) # 静态方法 @staticmethod def show_1(args1, args2): print(args1, args2) bj = Province("北京") bj.show() # 调用普通方法 Province.class_func() # 调用类方法 Province.show_1(**{"args1": 111, "args2": 222}) # 调用静态方法
3、属性
Python中的属性其实是普通方法的变种。
class Pager: def __init__(self, all_count): self.all_count = all_count @property # 属性 def all_pager(self): a1, a2 = divmod(self.all_count, 10) if a2 == 0: return a1 else: return a1 + 1 @all_pager.setter # 设置可编辑属性 def all_pager(self, value): print(value) @all_pager.deleter def all_pager(self): print("del all_pager") p = Pager(101) ret = p.all_pager # 定义属性后,可以通过字段的调用方式在使用方法 print(ret) p.all_pager = 101001 del p.all_pager # 增加删除属性后,方法可以被删除,不加xxx_deleter是不允许删除的
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Pager: def __init__(self, all_count): self.all_count = all_count def f1(self): a1, a2 = divmod(self.all_count, 10) if a2 == 0: return a1 else: return a1 + 1 def f2(self, value): print(value) def f3(self): print("del all_pager") foo = property(fget=f1, fset=f2, fdel=f3) # 属性的另外一种使用方式 p = Pager(101) ret = p.foo print(ret) p.foo = 101001 del p.foo
属性的调用,通俗说就是可以实现通过字段的形式来使用方法。
四、类成员修饰符
对于每一个类的成员而言都有两种形式:
- 公有成员,在任何地方都能访问
- 私有成员,只有在类的内部才能方法
# 修饰字段 class Foo: def __init__(self, name, age): self.name = name self.__age = age # 前面加两个"__",变成私有字段 def f1(self): print(self.name) print(self.__age) class Bar(Foo): @staticmethod def f2(): # 继承不能调用私有字段 try: print(__age) except Exception: print(name) obj = Foo("alex", 18) obj.f1() print(obj.name) # 外部可以调用公共字段 # print(obj.__age) # 外部不能调用私有字段 obj1 = Bar.f2()
ps:非要访问私有属性的话,可以通过 对象._类__属性名
五、类的特殊成员
六、其他
1、有序字典
class MyDict(dict): def __init__(self): self.list = list() super(MyDict, self).__init__() def __setitem__(self, key, value): self.list.append(key) super(MyDict,self).__setitem__(key, value) def __str__(self): temp_list = list() for key in self.list: value = self.get(key) temp_list.append('"{key}": "{value}"'.format(key=key, value=value)) temp_str = "{" + ",".join(temp_list) + "}" return temp_str obj = MyDict() obj["k1"] = 123 obj["k2"] = 456 print(obj)
2、设计模式——单例模式
class Foo: instance = None def __init__(self, name): self.name = name @classmethod def get_instance(cls): # cls 类名 if cls.instance: return cls.instance else: obj = cls("pesen") cls.instance = obj return obj obj1 = Foo.get_instance() print(obj1) obj2 = Foo.get_instance() print(obj2)