目录:
一、类与对象
二、访问限制
三、类属性
四、类方法
五、静态方法
六、继承
七、组合
八、单例模式(详细阐述见设计模式)
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
![](https://img.haomeiwen.com/i17476284/1ff6cbf3ce33c6e6.png)
- 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)
![](https://img.haomeiwen.com/i17476284/1ff6cbf3ce33c6e6.png)
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)
![](https://img.haomeiwen.com/i17476284/016464c7318d5e88.png)
对象的__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()) # 类对象调用类方法
![](https://img.haomeiwen.com/i17476284/c4fd301c2ca4c4ac.png)
类方法的一个用途就是用于对类属性进行获取与设置。
五、静态方法
通过@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())
![](https://img.haomeiwen.com/i17476284/d9e05d1ea5a0cc25.png)
六、继承
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__)
![](https://img.haomeiwen.com/i17476284/aedfb864dab2d39e.png)
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)
![](https://img.haomeiwen.com/i17476284/2c804b0d0444c347.png)
组合优于继承:多重继承时,只能继承一个同名属性(第一个父类的属性)。
八、单例模式
单例模式:一个类只能生成一个实例对象。即先创建一个类的实例对象,之后不管创建多少个,返回的永远都是第一个实例对象的内存地址。
示例:
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))
![](https://img.haomeiwen.com/i17476284/bb171a6085e2f744.png)
网友评论