美文网首页
Python面向对象

Python面向对象

作者: Recalcitrant | 来源:发表于2019-05-27 17:06 被阅读0次

目录:
一、类与对象
二、访问限制
三、类属性
四、类方法
五、静态方法
六、继承
七、组合
八、单例模式(详细阐述见设计模式)

Python OPP

一、类与对象

1.类的定义

class ClassName:
    def __new__(cls, *args, **kwargs):
        """
        系统自动调用,无需显式定义
        为对象分配内存,#一、先于构造方法被调用
        :param args:
        :param kwargs:
        :return:
        """
        print("__new__")
        return super().__new__(cls)

    def __init__(self, 参数列表):
        """
        构造方法
        :param 参数1: 
        :param 参数2: 
        .........
        """
        print("__init__")
        self.成员变量1 = 参数1
        self.成员变量2 = 参数2
        .........
        
    def 成员方法1(self, 参数列表):
          print("__new__")
           pass
            
    def 成员方法2(self, 参数列表):
          pass
    
    .........

2.生成对象

当一个类定义完成之后,可以使用这个类来创建对象。

对象名 = 类名(参数列表)

参数列表中的参数会被传入构造方法。

创建对象时,系统先后自动调用__new__方法和__init__方法。
__new__方法为生成的实例对象分配内存。
__init__方法为生成的实例对象完成初始化。

3.isinstance()方法

isinstance(对象,类)

子类的实例对象也是父类的实例。

二、访问限制

_var:变量名前一个下划线来定义,此变量为保护成员protected。只有类及其子类可以访问。此变量不能通过from XXX import xxx 导入
__var:变量名前两个下划线来定义,此变量为私有成员private。只允许类本身访问,连子类都不可以访问。
__var__:系统定义的特殊成员。

1.私有成员

定义方式

在定义属性或方法时,在属性名或者方法名前增加两个下划线__即可。
双下划线开头的属性名或者方法名会被转换为:_类名__属性名(方法名)

访问方式

  • 1.通过自定义get,set方法提供私有属性的访问接口
    示例:
class Person:
    def __init__(self, name, age):
        self.name = name
        self.__age = age

    # 定义对私有属性获取的get方法,获取私有属性
    def get_age(self):
        return self.__age

    # 定义对私有属性重新赋值的set方法,重置私有属性
    def set_age(self, age):
        self.__age = age

通过set方法可以实现对属性赋值的规范化。

  • 2.调用property方法提供私有属性的访问

property()方法:

property(fget=None, fset=None, fdel=None, doc=None)

fget :用于获取属性值的函数
fset :用于设置属性值的函数
fdel :用于删除属性值的函数
doc :属性对象创建文档字符串

示例:

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

    # 定义对私有属性的get方法,获取私有属性
    def getAge(self):
        return self.__age

    # 定义对私有属性的重新赋值的set方法,重置私有属性
    def setAge(self, age):
        self.__age = age

    p = property(getAge, setAge)       # 注意里面getAge,setAge不能带()


s1 = Person("jack", 22)
s1.p = 23       # 如果使用=,则会判断为赋值,调用setAge方法。
print(s1.name, s1.p)     # jack 23   ,直接使用s1.p会自动判断会取值,调用getAge
运行结果
  • 3.使用@property标注提供私有属性的访问

在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把变量随便改。
使用@property装饰器使得变量既可以通过getter和setter方法来获取和设置,又可以使得操作与直接暴露一致。

@property           # get方法装饰器
@变量名.setter       # set方法装饰器

示例:

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

    @property           # @proterty下面默认跟的是get方法,如果设置成set会报错。
    def age(self):
        return self.__age

    @age.setter         # set方法
    def age(self, age):
        self.__age = age


s1 = Person("jack", 22)
s1.age = 23
print(s1.name, s1.age)
运行结果

2.保护成员

定义方式

在定义属性或方法时,在属性名或者方法名前增加一个下划线_即可。
单下划线开头的属性名或者方法名会被转换为:_属性名(方法名)

访问方式

本类及其子类可直接访问。

三、类属性

类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本,与C++、Java中类的静态成员变量类似。
示例:

class Person:
    count = 0

    def __init__(self, name, age):
        self.name = name
        self.age = age
        Person.count += 1


s1 = Person("Zhangsan", 20)
s2 = Person("Lisi", 22)
s3 = Person("Wangwu", 25)
print(s1.__dict__)
print(s2.__dict__)
print(s3.__dict__)
print(Person.count)
运行结果

对象的__dict__属性查看不到类属性。

四、类方法

通过@classmethod装饰器修饰的方法即为类方法。

类方法的第一个参数必须是类对象,一般以cls作为第一个参数(当然也可以用其他名称的变量作为其第一个参数,但是大部分人都习惯以'cls'作为第一个参数的名字),通过类对象或实例对象去访问。
示例:

class Person:
    country = "China"

    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def creat_person(cls, name, age):
        print(cls)
        person = cls(name, age)
        person.name = name
        person.age = age
        return person

    @classmethod
    def get_country(cls):
        return cls.country

    @classmethod
    def set_country(cls, country):
        cls.country = country


s1 = Person.creat_person("Zhangsan", 20)
print(s1.get_country())         # 实例对象调用类方法
print(Person.get_country())     # 类对象调用类方法

Person.set_country("USA")
print(s1.get_country())         # 实例对象调用类方法
print(Person.get_country())     # 类对象调用类方法
运行结果

类方法的一个用途就是用于对类属性进行获取与设置。

五、静态方法

通过@staticmethod装饰器修饰的方法即为静态方法。

静态方法的参数无规定,可当作普通函数,一般用于写工具类,通过类对象或实例对象调用。
示例:

class Person:
    country = "China"

    def __init__(self, name, age):
        self.name = name
        self.age = age

    @staticmethod
    def sum_age(age1, age2):
        return age1 + age2

    @staticmethod
    def get_country():
        return Person.country


s1 = Person("Zhangsan", 20)
s2 = Person("Lisi", 22)
print(Person.sum_age(s1.age, s2.age))
print(Person.get_country())
运行结果

六、继承

1.继承语法

class 类名(父类名1, 父类名2, ......):
    pass

子类 继承自 父类,可以直接享受父类中已经封装好的方法,无需再次开发。
父类 的方法实现不能满足 子类 需求时,可以对方法进行 重写(override)
子类 中应该根据 职责,封装子类特有的 属性和方法

2.继承顺序

父类的继承顺序与继承书写顺序有关。

3.类的__mro__属性

返回一个类元组,在方法解析查找基类时将考虑的类的顺序。
示例:

class A:
    def __init__(self):
        pass


class B:
    def __init__(self):
        pass


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


print(C.__mro__)
运行结果

object类是所有类的父类。

七、组合

类的组合:在一个类中以另外一个类的对象作为属性。
示例:

class A:
    def __init__(self):
        self.name = 'A'


class B:
    def __init__(self):
        self.name = 'B'


class C:
    def __init__(self):
        self.a = A()
        self.b = B()
        self.name = 'C'


c = C()
print(c.a.name)
print(c.b.name)
print(c.name)
运行结果

组合优于继承:多重继承时,只能继承一个同名属性(第一个父类的属性)。

八、单例模式

单例模式:一个类只能生成一个实例对象。即先创建一个类的实例对象,之后不管创建多少个,返回的永远都是第一个实例对象的内存地址。
示例:

class S:
    instance = None

    def __new__(cls, *args, **kwargs):
        if S.instance is None:
            S.instance = super().__new__(cls)

    def __init__(self):
        pass


s1 = S()
print(id(s1))
s2 = S()
print(id(s2))
运行结果

相关文章

网友评论

      本文标题:Python面向对象

      本文链接:https://www.haomeiwen.com/subject/lxsazqtx.html