方法没有重载
方法的动态性
Python是动态语言,我们可以动态的为类添加新的方法,或者动态的修改类的已有的方法。
class Person:
def work(self):
print("work")
def work2(self):
print("work2")
Person.work2 = work2 # 方法连接
p = Person()
p.work()
p.work2()
私有属性和私有方法
Python 对于类的成员没有严格的访问控制限制,这与其他面向对象语言有区别。
1.通常我们约定,两个下划线开头的属性是私有的(private)。其他为公共的(public)。
2.类内部可以访问私有属性(方法)
3.类外部不能直接访问私有属性(方法)
4.类外部可以通过“类名_私有属性(方法)名”访问私有属性(方法)
【注】方法本质上也是属性,只不过是可以通过()执行而已。所以,此处讲的私有属性和公有属性,也同时讲解了私有方法和公有方法的用法。如下测试中,同时也包含了私有方法和公有方法的例子。
class Employee:
__company = 'company'
def __init__(self, name, age):
self.name = name
self.__age = age # 私有属性
def __work(self): # 私有方法
print(Employee.__company)
e = Employee('Cat', 18)
e._Employee__work()
>>> company
print(Employee._Employee__company)
>>> company
print(e._Employee__age)
>>> 18
print(dir(e))
>>> ['_Employee__age', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']
@property 装饰器
# 公有属性基操
class Employee:
def __init__(self, salary):
self.salary = salary # 改成__salary则不可直接访问
e = Employee(3000)
e.salary = -2000
print(e.salary)
>>> -2000
# 普通方式更改私有属性基操
class Employee1:
def __init__(self, salary):
self.__salary = salary
def get(self):
return self.__salary
def set(self,salary):
if 1000<salary<50000:
self.__salary = salary
else:
print('False')
# 直接e.__salary报错
e = Employee1(3000)
e.set(2000)
print(e.get())
>>> 2000
# @property调用私有属性
class Employee2:
def __init__(self, salary):
self.__salary = salary
@property # 相当于get
def salary(self):
return self.__salary
@salary.setter # 相当于set
def salary(self,salary):
if 1000<salary<50000:
self.__salary = salary
else:
print('False')
e = Employee2(3000)
e.salary = 2000
print(e.salary)
>>> 2000
面向对象三大特征
封装(利用私有属性和方法)、继承、多态
继承
- class 子类(父类1,[父类2……]) 可以继承多个父类
- 私有属性方法被继承,但是不可直接使用
- 如果在类定义中没有指定父类,则默认父类是object类。也就是说, object是所有类的父类,里面定义了一些所有类共有的默认实现,比如:__new__()
class Person:
def haha(self):
print('haha')
class Student():
pass
s = Student()
s.haha()
>>> haha
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class Student(Person):
def __init__(self, name, age, score):
Person.__init__(self, name, age) # 必须是显示函数,否则不调用
self.score = score
print(Student.mro()) # method resolution order 方法解析顺序,即类的层次结构
>>> [<class '__main__.Student'>, <class '__main__.Person'>, <class 'object'>]
s = Student('Lucy', 18, 60)
print(s.name)
>>> Lucy
class Person:
def __init__(self, name, age):
self.name = name
self.__age = age
class Student(Person):
def __init__(self, name, age, score):
Person.__init__(self, name, age) # 必须是显示函数,否则不调用
self.score = score
def __str__(self): # 使对象可以直接被打印
return "my name is {0}".format(self.name)
s = Student('Lucy', 18, 60)
print(dir(s))
>>> ['_Person__age', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name', 'score']
print(s._Person__age)
>>> 18
print(s)
>>> my name is Lucy
>>>
方法的重写
子类可以重新定义父类中的方法,即覆盖父类的方法,相同函数,子类优先
object根类
多重继承
super()获取父类定义(而非对象)
class A:
def say(self):
print("A", self)
class B(A):
def say(self):
A.say(self) # 方法1
super().say() # 方法2
print("B", self)
B().say()
多态
class Man:
pass
class Chinese(Man):
def eat(self):
print("chopsticks")
class English(Man):
def eat(self):
print("fork")
def ManEat(m):
if isinstance(m, Man): # 根据不同对象调用不同方法(Chinese/English)
m.eat()
else:
print("不能吃饭")
ManEat(Chinese)
>>> "不能吃饭"
ManEat(Chinese())
>>> "chopsticks"
特殊方法和运算符重载
# 关于加法
a + b
a.__add__(b)
class Person:
def __init__(self, name):
self.name = name
def __add__(self, other): # 两个人名
if isinstance(other, Person): # 对象类型是否相同
print('{0}{1}'.format(self.name, other.name))
else:
print('类型不同不能相加')
def __mul__(self, other): # 乘法
if isinstance(other, int):
print(self.name*other)
else:
print('类型不同不能相乘')
p1 = Person('cat')
p2 = Person('dog')
print(p1+p2)
>>> catdog
print(p1*5)
>>> catcatcatcatcat
特殊属性
class A:
pass
class B:
pass
class C(B,A):
def __init__(self, nn):
self.nn = nn
def cc(self):
print('haha')
c = C(3)
print(dir(c))
print(c.__dict__) # 特殊属性
print(c.__class__)
print(C.__bases__)
print(C.mro())
print(A.__subclasses__())
深拷贝和浅拷贝内存
赋值:内外对象不变
浅拷贝:外部对象变化,内部对象不变
深拷贝:全部重新复制
组合
内外对象组合,self.a = a,a可以指对象,通过组合实现继承
class A:
def say():
print('AAAA')
class B:
def __init__(self,a):
self.a = a
a = A()
b = B(a)
b.a.say()
>>> AAAA
-
“is—a”关系使用继承,从而实现子类拥有的父类的方法和属性。“is—a”关系指的是类似这样的关系:狗是动物, dog is animal,狗类就应该继承动物类
-
“has—a”关系使用组合 ,也能实现一个类拥有另一个类的方法和属性。"has-a"关系指的是这样的关系:手机拥有CPU. MobilePhone has a CPU.
设计模式——工厂模式实现(GOF23)
设计模式——单例模式
单例模式(Singleton Pattern)的核心作用是确保一个类只有一个实例,并且提供一个访问该实例的全局访问点。
单例模式只生成一个实例对象,减少了对系统资源的开销。当一个对象的产生需要比较多的资源,如读取配置文件、产生其他依赖对象时,可以产一个“单例对象”,然后永久驻留内存中,从而极大的降低开销。
class MySingleton:
__obj = None # 用于存放类属性
__init_flag = True # 设置只能初始化一次
def __new__(cls, *args, **kwargs):
if cls.__obj == None:
cls.__obj = object.__new__(cls)
return cls.__obj
def __init__(self.name):
if MySingleton.__init_flag:
print("init")
self.name = name
MySingleton.__init_flag = False # 初始化一次后结束
a = MySingleton('a')
b = MySingleton('b')
print(a)