1、方法没有重载

Python 中,方法的的参数没有声明类型(调用时确定参数的类型),参数的数量可由可变参数控制。因此,Python 中是没有方法的重载的。
定义一个方法即可有多种调用方式,相当于实现了其他语言中的方法的重载。
如果我们在类体中定义了多个重名的方法,只有最后一个方法有效。
建议:不要使用重名的方法!Python 中方法没有重载。
举例:

# Python中没有方法的重载,定义多个同名方法,只有最后一个有效

class Person:
    def say_hi(self):
        print("hello")

    def say_hi(self,name):
        print("{0},hello".format(name))

p1 = Person()
# p1.say_hi()   #TypeError: say_hi() missing 1 required positional argument: 'name'
p1.say_hi("SSS")

2、方法的动态性

Python 是动态语言,我们可以动态的为类添加新的方法,或者动态的修改类的已有的方法。
举例:

# 测试方法的动态性

class Person:
    def work(self):
        print("努力上班!")

def play_game(self):
    print("{0}玩游戏".format(self))

def work2(s):
    print("好好工作,努力上班!")

Person.play = play_game
Person.work = work2
p = Person()
p.play()
p.work()

测试结果:

python 方法重载 python类方法重载_python


从测试结果可以看出,Person动态的新增了play_game方法,以及work2替换了work方法。

3、私有属性和私有方法(实现封装)

关于私有属性和私有方法,有如下要点:
1. 通常我们约定,两个下划线开头的属性是私有的(private)。其他为公共的(public)。
2. 类内部可以访问私有属性(方法)
3. 类外部不能直接访问私有属性(方法)
4. 类外部可以通过“_类名__私有属性(方法)名”访问私有属性(方法)
注:方法本质上也是属性,只不过是可以通过()执行而已。

举例:

# 测试私有属性、私有方法

class Employee:
    __company = "程序猿"  # 私有类属性  通过dir可以查到

    def __init__(self, name, age):
        self.name = name
        self.__age = age        # 私有实例属性

    def say_company(self):
        print("我的公司是:", Employee.__company)  # 类内部可以直接访问私有属性
        print(self.name, "的年龄是:", self.__age)
        self.__work()

    def __work(self):      # 私有实例方法  通过dir可以查到_Employee__work
        print("工作!好好工作,好好赚钱。")

p1 = Employee("kdx", 22)
print(p1.name)
print(dir(p1))
p1.say_company()
print(p1._Employee__age)   # 通过这种方式直接访问到私有属性。通过dir可以查到属性:_Employee__age
# print(p1.__age) # 直接访问私有属性,报错

测试:

python 方法重载 python类方法重载_开发语言_02


注:从打印的 Person 对象所有属性我们可以看出。私有属性“__age”在实际存储时是按照“_Person__age”这个属性来存储的。这也就是为什么我们不能直接使用“__age”而可以使用“_Person__age”的根本原因

4、@property装饰器

@property 可以将一个方法的调用方式变成“属性调用”
举例:

# 测试@property

class Employee:

    @property
    def salary(self):
        return 10000

emp = Employee()
print(emp.salary)    # 打印10000
print(type(emp.salary))  #打印<class 'int'>
# emp.salary()   # TypeError: 'int' object is not callable
# mp.salary = 2000  # @property 修饰的属性,如果没有加 setter 方法,则为只读属性。
                    # 此处修改报错AttributeError: can't set attribute

测试结果:

python 方法重载 python类方法重载_父类_03


注:@property 主要用于帮助我们处理属性的读操作、写操作。对于某一个属性,我们可以直接通过:
emp.salary = 30000
如上的操作读操作、写操作。但是,这种做法不安全。比如,我需要限制薪水必须为 1-10000的数字。这时候,我们就需要通过 getter、setter 方法

举例:

# 测试@property

class Employee:
    def __init__(self, name, salary):
        self.name = name
        self.__salary = salary

    @property     # 相当于salary属性的getter方法
    def salary(self):
        print("月薪为{0},年薪为{1}".format(self.__salary, self.__salary*12))
        return self.__salary

    @salary.setter
    def salary(self, salary):    # 相当于salary属性的setter方法
        if(0 < salary < 1000000):
            self.__salary = salary
        else:
            print("薪水录入错误!只能在0-1000000之间!")

emp1=Employee("kdx", 100)
print(emp1.salary)

emp1.salary = 200
print(emp1.salary)

测试结果:

python 方法重载 python类方法重载_父类_04

5、属性和方法命名总结

· _xxx:保护成员,不能用“from module import * ”导入,只有类对象和子类对象能访问这些成员。
· xxx:系统定义的特殊成员
· __xxx: 类中的私有成员,只有类对象自己能访问,子类对象也不能访问。(但,在类外部可以通过“对象名. _类名__xxx”这种特殊方式访问。Python 不存在严格意义的私有成员)

注:再次强调,方法和属性都遵循上面的规则。

6、继承

语法格式:
Python支持多重继承,一个子类可以继承多个父类。继承的语法格式如下:
class 子类类名(父类1[,父类2,…]):
类体
如果在类定义中没有指定父类,则默认父类是 object 类。也就是说,object 是所有类的父类,里面定义了一些所有类共有的默认实现,比如:new()。

举例:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.__age = age

    def say_age(self):
        print(self.name, "的年龄是:", self.__age)

class Student(Person):
    def __init__(self, name, age, score):
        self.score = score
        Person.__init__(self, name, age)  # 构造函数中包含调用父类构造函数。根据需要,不是必须。
                                          # 子类并不会自动调用父类的的__init__(),我们必须显式的调用它

s1 = Student("SSS ", 20, 100)
s1.say_age()
print(dir(s1))

注:构造函数中包含调用父类构造函数。根据需要,不是必须。子类并不会自动调用父类的的__init__(),我们必须显式的调用它

7、类成员的继承与重写

1. 成员继承:子类继承了父类除构造方法之外的所有成员。
2. 方法重写:子类可以重新定义父类中的方法,这样就会覆盖父类的方法,也称为“重写”

如图所示:

python 方法重载 python类方法重载_私有属性_05

8、查看类的继承层次结构

通过类的方法mro()可以输出这个类的继承层次机构。

举例:

python 方法重载 python类方法重载_父类_06


结果:

[<class ‘main.C’>, <class ‘main.B’>, <class ‘main.A’>, <class ‘object’>]

python 方法重载 python类方法重载_私有属性_07

9、object根类

object类是所有类的父类,所以所有的类都有object类的属性和方法。

10、重写__str__()方法

object 有一个__str__()方法,用于返回一个对于“对象的描述”,对应于内置函数 str()经常用于 print()方法,帮助我们查看对象的信息。str()可以重写。
举例:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.__age = age

    def __str__(self):      # 将对象转化成一个字符串,一般用于 print 方法
        return "名字是:{0},年龄是{1}".format(self.name, self.__age)


p = Person("SSS", 19)
print(p)

11、多重继承

举例:

python 方法重载 python类方法重载_python 方法重载_08


注:这样会使类的整体层次搞的异常复杂,尽量避免使用。

12、MRO()

Python支持多继承,如果父类中有相同名字的方法,在子类没有指定父类名时,解释器将“从左向右”按顺序搜索。

MRO(Method Resolution Order):方法解析顺序。 我们可以通过 mro()方法获得“类的层次结构”,方法解析顺序也是按照这个“类的层次结构”寻找的。

如下图所示:

python 方法重载 python类方法重载_私有属性_09

13、super()获得父类定义

在子类中,如果想获得父类的方法,我们可以通过super()来做。
super()代表父类的定义,不是父类对象。
举例:

# super获得父类定义


class A:
    def say(self):
        print("A:", self)
        print("say AAAA")


class B(A):
    def say(self):
        # A.say(self)  # 调用父类的方法
        super().say()  # 通过super()调用父类的方法
        print("say BBB")


b = B()
b.say()

测试结果:

python 方法重载 python类方法重载_开发语言_10

14、多态

多态是指同一个方法调用由于对象不同可能产生不同的行为。
注:
1、多态是方法的多态,属性没有多态。
2、多态的存在有2个必要条件:继承、方法重写。
举例:

# 多态


class Animal:
    def shout(self):
        print("动物叫了一声")


class Dog(Animal):
    def shout(self):
        print("小狗,汪汪汪")


class Cat(Animal):
    def shout(self):
        print("小猫,喵喵喵")


def animalshout(a):
    if isinstance(a, Animal):    # 如果指定的对象拥有指定的类型,则 isinstance() 函数返回 True,否则返回 False。
        a.shout()   # 传入的对象不同,shout 方法对应的实际行为也不同。


animalshout(Dog())
animalshout(Cat())

测试结果:

python 方法重载 python类方法重载_私有属性_11

15、Python isinstance() 函数

python 方法重载 python类方法重载_私有属性_12


python 方法重载 python类方法重载_python 方法重载_13


举例:

class MyObj:
    name = "Bill"


y = MyObj()

x = isinstance(y, MyObj)

print(x)

结果:

python 方法重载 python类方法重载_python_14

16、特殊方法和运算符重载

常见的特殊方法统计如下:

python 方法重载 python类方法重载_私有属性_15


每个运算符都有相应的方法,统计如下:

python 方法重载 python类方法重载_父类_16


python 方法重载 python类方法重载_父类_17


举例:

a = 12
b = 32
c = a + b
d = a.__add__(b)
print("c=", c)
print("d=", d)

运算结果:

python 方法重载 python类方法重载_父类_18


举例:实现运算符的重载

# 测试运算符的重载


class Person:
    def __init__(self, name):
        self.name = name

    def __add__(self, other):
        if isinstance(other, Person):
            return "{0}--{1}".format(self.name, other.name)
        else:
            return "不是同类对象,不能相加"

    def __mul__(self, other):
        if isinstance(other, int):
            return self.name*other
        else:
            return "不是同类对象,不能相乘"


p1 = Person("kdx")
p2 = Person("SSS")

x = p1 + p2
print(x)

print(p1 * 3)

17、特殊属性

Python对象中包含了很多双下划线开始和结束的属性,这些是特殊属性,有特殊用法。

python 方法重载 python类方法重载_私有属性_19


举例:

# 测试特殊属性

class A:
    pass


class B:
    pass


class C(B, A):
    def __init__(self, nn):
        self.nn = nn

    def cc(self):
        print("cc")


c = C(3)
print(dir(c))
print(c.__dict__)
print(c.__class__)    # c所属的类
print(C.__bases__)    # c的基类(多继承)
print(C.mro())        # c类的层次结构
print(A.__subclasses__())   # A的子类列表

测试结果:

python 方法重载 python类方法重载_python 方法重载_20

18、对象的浅拷贝和深拷贝(理解)

举例:

import copy


class MobilePhone:
    def __init__(self, cpu, screen):
        self.cpu = cpu
        self.screen = screen


class CPU:
    def calculate(self):
        print("算不出来")
        print("cpu对象", self)


class Screen:
    def show(self):
        print("显示一个好看图片")
        print("screen对象", self)


# 测试变量赋值
c1 = CPU()
c2 = c1
print(c1)
print(c2)

# 测试浅复制
print("测试浅复制......")
s1 = Screen()
m1 = MobilePhone(c1, s1)
m2 = copy.copy(m1)
print(m1, m1.cpu, m1.screen)
print(m2, m2.cpu, m2.screen)

# 测试深复制
print("测试深复制......")
m3 = copy.deepcopy(m1)
print(m1, m1.cpu, m1.screen)
print(m3, m3.cpu, m3.screen)

测试结果:

python 方法重载 python类方法重载_python 方法重载_21

19、组合

“is-a”关系,我们可以使用“继承”。从而实现子类拥有的父类的方法和属性。“is-a”关系指的是类似这样的关系:狗是动物,dog is animal。狗类就应该继承动物类。

“has-a”关系,我们可以使用“组合”,也能实现一个类拥有另一个类的方法和属性。”has-a”关系指的是这样的关系:手机拥有 CPU。 MobilePhone has a CPU。
举例:

# 组合测试


class MobilePhone:
    def __init__(self, cpu, screen):
        self.cpu = cpu
        self.screen = screen


class CPU:
    def calculate(self):
        print("算不出来")
        print("cpu对象", self)


class Screen:
    def show(self):
        print("显示一个好看图片")
        print("screen对象", self)


c = CPU()
s = Screen()
m = MobilePhone(c, s)
m.cpu.calculate()  # 通过组合,我们也能调用cpu对象的方法。相当于手机对象间接拥有了“cpu的方法”
m.screen.show()

测试结果:

python 方法重载 python类方法重载_私有属性_22

20、设计模式_工厂模式

工厂模式实现了创建者和调用者的分离,使用专门的工厂类将选择实现类、创建对象进行统一的管理和控制。
举例:

# 工厂模式


class CarFactory:
    def createCar(self, brand):
        if brand == "奔驰":
            return Benz()
        elif brand == "宝马":
            return BMW()
        elif brand == '比亚迪':
            return BYD()
        else:
            return "未知品牌,无法创建"


class Benz:
    pass


class BMW:
    pass


class BYD:
    pass


factory = CarFactory()
c1 = factory.createCar("奔驰")
c2 = factory.createCar("宝马")
print(c1)
print(c2)

测试结果:

python 方法重载 python类方法重载_父类_23

21、设计模式_单例模式

单例模式(Singleton Pattern)的核心作用是确保一个类只有一个实例,并且提供一个访问该实例的全局访问点。
单例模式只生成一个实例对象,减少了对系统资源的开销。当一个对象的产生需要比较多的资源,如读取配置文件、产生其他依赖对象时,可以产生一个“单例对象”,然后永久驻留内存中,从而极大的降低开销。
举例:

# 单例模式


class MySingleton:
    __obj = None
    __init_flag = True

    def __new__(cls, *args, **kwargs):
        if cls.__obj is 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("aa")
print(a)
b = MySingleton("bb")
print(b)

测试结果;

python 方法重载 python类方法重载_python 方法重载_24

22、测试工厂模式和单例模式的整合使用

举例理解:

# 测试工厂模式和单例模式的整合使用


class CarFactory:
    __obj = None  # 类属性
    __init_flag = True

    def create_car(self, brand):
        if brand == "奔驰":
            return Benz()
        elif brand == "宝马":
            return BMW()
        elif brand == "比亚迪":
            return BYD()
        else:
            return "未知品牌,无法创建"

    def __new__(cls, *args, **kwargs):
        if cls.__obj is None:
            cls.__obj = object.__new__(cls)
            return cls.__obj

    def __init__(self):
        if CarFactory.__init_flag:
            print("init CarFactory....")
            CarFactory.__init_flag = False


class Benz:
    pass


class BMW:
    pass


class BYD:
    pass


factory = CarFactory()
c1 = factory.create_car("奔驰")
c2 = factory.create_car("比亚迪")
print(c1)
print(c2)

factory2 = CarFactory()
print(factory)
print(factory2)

测试结果:

python 方法重载 python类方法重载_开发语言_25