Python_面向对象扩展_实例和类属性_实例与类和静态方法_魔术方法_反射_设计模式(12)

目录:

一、实例属性和类型属性
二、实例方法、类方法、静态方法
三、魔术方法
四、反射
五、设计模式

创作不易,各位看官,点个赞收藏、关注必回关、QAQ、您的点赞是我更新的最大动力!

Python_面向对象扩展_实例和类属性_实例与类和静态方法_魔术方法_反射_设计模式(12)_第1张图片 Python_面向对象扩展_实例和类属性_实例与类和静态方法_魔术方法_反射_设计模式(12)_第2张图片

一、实例属性与类属性

实例属性 在实例对象中定义的属性(在__init__中定义的属性)
类属性 在类中定义的属性(类里面,方法外部),多个实例对象共享一份属性

(一)实例属性的声明和访问

1.声明
实例属性的声明,包含在类型__init__()初始化方法中,使用self关键字属性绑定在当前对象上

def __init_(self,name,age):
    """实例属性初始化"""
    self.name = name 
    self.age = age

2.访问
实例属性在类型内部可以通过self关键字应用,在类型外部可以同归对象引用变量访问访问和修改

  class User:
  def __init__(self,name,age):
  	"""实例属性初始化"""
  	self.name = name
  	self.age = age
  user = User("zs"18)
  print(user.name)

(二)类属性的声明和访问

1.声明
类里面,方法外部

#数据类型
class Data:
	courses_dict = {}

2.访问
类属性能被当前类型的所有对象访问,或者直接通过类型名称访问

#数据类型
class Data:
	courses_dict = {}
#使用实例对象访问
data = Data()
print(data.courses_dict)
#使用类对象访问
print(Data.courses_dict)

(三)修改

不可变类型:

  • 对象名.属性名=属性值 给对象添加属性,而不是进行修改

可变类型:

  • 如果对象是修改可变类型数据,是真正的修改
  • 如果是重新给可变类型变量赋值,则是给对象添加属性

例子一 不可变数据类型
其实相当于实例对象,和类对象两片空间

# 数据类型
class Data:
    """数据类型"""

	# 不可变数据类型
    courses_dict = "Python"

data = Data()
# 使用类对象修改课程为"java"
data.courses_dict = "UI"
Data.courses_dict = "java"
# 使用实例对象访问
print(data.courses_dict)  # 输出得到 UI
# 使用类对象访问
print(Data.courses_dict)  # 输出得到 java

例子二 可变数据类型:
会发现都修改了

# 数据类型
class Data:
    """数据类型"""
	# 可变数据类型
    courses_dict = ["Python"]

data = Data()
# 如果类属性为可变数据类型,则使用实例对象或者类对象都是真正的修改
Data.courses_dict.append("Java")
# 使用实例对象添加
data.courses_dict.append("PHP")
# 使用实例对象访问
print(data.courses_dict) # ['Python', 'Java', 'PHP']
# 使用类对象访问
print(Data.courses_dict) # ['Python', 'Java', 'PHP']

总结
类可以调用实例方法,静态方法,类方法和类属性,但是不能调用实例属性
实例对象可以调用实例方法,类方法,静态方法,类属性,实例属性
实例对象可以调用所有方法和属性,而类除了不能调用实例属性,其他的方法和属性都可以调用

测试代码 注释那就是类调用了实例属性,报错。

class User:
	def __init__(self, name, age):
		"""实例属性初始化"""
		self.name = name
		self.age = age

	def introduce(self):
		print(f"我叫{self.name},今年{self.age}岁")


user = User("zs", 18)
user.introduce()
User.introduce(user)
# print(User.name)  # 类对象不能调用实例属性

返回文章目录

二、实例方法、类方法、静态方法

(一)实例方法
  • 实例方法或者叫对象,指的是在类中定义的普通方法

  • 访问类属性,访问对象数据

  • 只有实例化对象之后才使用的方法,该方法的第一个参数接收的一定是对象本身!

class User:

    def introduce(self):
        print("这是实例方法中的代码")

user = User()
# 通过对象调用实例方法
user.introduce()

(二)类方法

  • 类方法:声明在类的内部,方法上使用装饰器 @classmethod
  1. 第一个参数是当前类型本身,约定俗称是cls;类方法执行访问当前类型的类属性,不能访问任何对象的实例属性;类方法被当前类型调用,也能被实例对象调用

  2. 应用场景:当一个方法中只涉及到静态属性的时候可以使用类方法(类方法可以修改类属性)不用访问实例属性

  3. 只能访问类型属性,不能访问实例属性

class Data:
    student_dic = dict()

    @classmethod
    def get_student_dic(cls):
        """获取学生信息"""
        return cls.student_dic

    @classmethod
    def set_student_dic(cls, stu_dic):
        cls.student_dic = stu_dic

print(Data.get_student_dic())  # 得到结果 {}
Data.set_student_dic(1)    # 修改值为 1
print(Data.get_student_dic())  # 得到结果 1

(三)静态例方法

  • 静态方法:是被统一管理在类中的函数,声明在类的内部

    1.格式:在方法添加@staticmethod

    2.参数:静态方法可以有参数,页可以无参数

    3.应用场景:一般用于和类对象以及实例对象无关的代码

    4.使用方式:类名.方法名()(或者对象名.方法名())

    5.不能访问实例属性,不能访问类型属性

  import time
  class Views:
      """界面类型"""
      @staticmethod
      def get_current_time():
          #获取当前时间
          now = time.localtime()
          return time.strftime("%Y-%m-%d %H:%M:%S",now)
  
  print(Views.get_current_time())

(四)总结

Python_面向对象扩展_实例和类属性_实例与类和静态方法_魔术方法_反射_设计模式(12)_第3张图片
Python_面向对象扩展_实例和类属性_实例与类和静态方法_魔术方法_反射_设计模式(12)_第4张图片
返回文章目录

三、魔术方法

(一)常见的魔术方法

1.构造和初始化

名称 描述
_ _ new_ _(cls) 创建对象的魔法方法
_ _ init_ _(self) 初始化对象数据的方法

2.比较运算符

名称 描述
_ _ cmp _ _ (self,other) 1大于其他数、0等于其他数、-1小于其他数
_ _ eq _ _ (self,other) 定义符号==的操作
_ _ ne _ _ (self,other) 定义符号!=的操作
_ _ lt _ _ (self,other) 定义符号<的操作
_ _ gt _ _ (self,other) 定义符号>的操作
_ _ le _ _ (self,other) 定义符号>=的操作
_ _ ge _ _ (self,other) 定义符号>=的操作

3.算术运算符

名称 描述
_ _ add _ _ (self,other) 定义符号+的操作
_ _ sub _ _ (self,other) 定义符号-的操作
_ _ mul _ _ (self,other) 定义符号*的操作
_ _ floordiv _ _(self,other) 定义符号//的操作
_ _ div _ _(self,other) 定义符号/的操作
_ _ pow _ _(self,other) 定义符号**的操作

4.增量赋值

名称 描述
_ _ iadd _ _(self,other) 定义符号+=的操作
_ _ isub _ _(self,other) 定义符号-=的操作
_ _ imul _ _(self,other) 定义符号*=的操作
_ _ ifloordiv _ _(self,other) 定义符号//=的操作
_ _ idiv _ _(self,other) 定义符号/=的操作
_ _ ipow _ _(self,other) 定义符号**=的操作

5.对象打印

名称 描述
_ _ str _ _(self) 打印展示对象信息
_ _ repr _ _(self) 输出展示对象信息

(二)部分魔术方法使用

call 打印

class User:

    def __call__(self, *args, **kwargs):
        print("测试用户A")

    def introduce(self):
        print("测试用户B")
user = User()

# 不需要创建对象 可以直接调用
user()

# 传统使用
user.introduce()

del 删除

# class User:
#
#     def __init__(self,name):
#
#         print("init方法对象初始化")
#         self.name = name
#
#
#     def __del__(self):  # 最后执行
#         print("对象即将被删除")
#
#
# user =  User("zs")
# print("代码执行结束")
#
class User:

    def __init__(self,name):

        print("init方法对象初始化")
        self.name = name


    def __del__(self):  # 最后执行
        print("对象即将被删除")

def func():
    user =  User("zs")
func()
print("代码执行结束")


eq 比较

class User:

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


    def __eq__(self, other):

        #比较部分属性
        # return self.age == other.age

        # 比较所有属性
        return self.__dict__ == other.__dict__


user1 = User("小王",20)
user2 = User("小王",20)
print(user1==user2)


new 创建对象

class User:

    def __init__(self):

        print("初始化")
        self.name = name
        self.age = range

    def __new__(cls, *args, **kwargs):
        print("开始创建对象")
        return  object.__new__(cls)

user =  User("zs",18)

# print(user.name)
print(user)

返回文章目录

四、反射

(一)什么是反射
  • 反射是编程语言中的一种高级操作方式,是在程序运行过程中,动态的从内存中获取执行状态,根据执行状态动态调用执行栈,完成具体功能的操作!

    反射就是不直接操作对象数据,而是通过字符串的对象描述,交给运行中的程序,有程序在运行时获取到字符串描述的对象数据,再去执行对象数据的操作,类似 eval()函数eval(“show_login()”)

    反射为了进行代码的黑盒调试,通过字符串描述反射得到对象的属性或者方法,完成目属性的获取或者方法的调用。反射未了容错开发,不确定目标对象是否已经完善了对应的函数/方法,直接调用执行并且保证程序不能出错。

(二)常见的反射

Python_面向对象扩展_实例和类属性_实例与类和静态方法_魔术方法_反射_设计模式(12)_第5张图片
基本案例:

"""
反射机制下的容错开发
"""


class Service: # 开发A
    """业务类型"""
    @staticmethod
    def login():
        input("用户登录了, 按任意键继续..")


class Views:  # 开发B
    """视图"""
    @staticmethod
    def show_login():
        res = input("输入1开始登录")
        if res == "1":
            # 多人协同下,下面的传统代码已经不满足开发需求!
            # return Service.login()
            # 反射容错开发:判断目标对象中是否包含 login()属性
            if hasattr(Service, "login"):
                # 如果包含[已经开发完成了],获取login()
                login = getattr(Service, "login")
                # 执行登录
                return login()
        input("选项非法,重新登录")
        return Views.show_login()

Views.show_login()

反射中的类和属性:

# getattr(obj,name) 获取对象/类中的成员值

class Teacher:
    dic = {"学生信息":"show_student","老师信息":"show_teacher"}

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

    @classmethod
    def func(cls):
        print("--func--")

    def show_student(self):
        print("--show_student--")
    def show_teacher(self):
        print("--show_teacher--")

# 反射类中的属性和方法
# 获取Teacher类中的dic
print(getattr(Teacher, "dic"))
# 获取Teacher类中的func
ret = getattr(Teacher,"func")
ret()

反射对象中的属性和方法:


class Teacher:
    dic = {"学生信息":"show_student","老师信息":"show_teacher"}

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

    @classmethod
    def func(cls):
        print("--func--")

    def show_student(self):
        print("--show_student--")
    def show_teacher(self):
        print("--show_teacher--")
        
# 反射对象中的属性和方法
teacher = Teacher("张老师",30)
# 获取name属性
print(getattr(teacher, "name"))
# 获取所有属性
print(getattr(teacher,"__dict__"))
ret = getattr(teacher,"show_student")
ret()

反射模块
test1:


name = "稳稳"

def func1():
    print("test1中的func1")

def func2(num):
    print("test1中的func2-->",num)

class Person:
    def study(self):
        print("正在学习。。。")
#反射模块中的属性和方法
import test1

#反射模块中的属性
print(getattr(test1,"name"))

#反射模块中的方法
func1 = getattr(test1,"func1")
func1()

func2 = getattr(test1,"func2")
func2(666)

#反射模块中的类
Person = getattr(test1,"Person")
per = Person()
per.study()

hasattr() 检测对象是否有某个成员,返回是布尔值

class Teacher:
    dic = {"学生信息":"show_student","老师信息":"show_teacher"}

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

    @classmethod
    def func(cls):
        print("--func--")

    def show_student(self):
        print("--show_student--")
    def show_teacher(self):
        print("--show_teacher--")

b = hasattr(Teacher,"dic")
if b:
    ret = getattr(Teacher,"dic")
    print(ret)
else:
    print("没有当前属性")

setattr() 设置或者添加对象/类中的成员

class Person:
    age = ""
    name = ""
    pass
#给Person添加静态属性age
setattr(Person,"age",18)
print(Person.age)

#delattr 删除对象或者类中的成员
per1 = Person()
setattr(per1,"name","张伟强")
print(per1.name)
#删除Person类中的age属性
delattr(Person,"age")
print(Person.age)

练习:

class Teacher:
    dic = {"学生信息":"show_student","老师信息":"show_teacher"}

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

    @classmethod
    def func(cls):
        print("--func--")

    def show_student(self):
        print("--show_student--")
    def show_teacher(self):
        print("--show_teacher--")

a = Teacher("测试",18)

key = input("输入查看信息: ")
if key == "学生信息":
    b = hasattr(Teacher, "dic")
    if b :
        ret = getattr(Teacher, "dic")
        print(ret["学生信息"])
    else:
        print("不存在")
elif key == "老师信息":
    b = hasattr(Teacher, "dic")
    if b :
        ret = getattr(Teacher, "dic")
        print(ret["老师信息"])
    else:
        print("不存在")
else:
    print("输入正确信息")

返回文章目录

五、设计模式

(一)什么是设计模式
软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、 代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。

软件设计模式:软件开发六原则-了解
1、开闭原则(OCP: Open Close Principle)
2、里氏代换原则
3、依赖倒转原则
4、迪米特法则
5、接口隔离原则
6、单一职责原则

软件设计模式:成熟的设计模式:23 种
1、创建型模式
2、结构型模式
3、行为型模式

标准单例模式:
得到两个结果内存地址一致

# 是否是第一次创建对象,如果是首次创建对象,则调用父类`__new__`()方法创建对象并返回
# ​如果不是第一创建对象,直接返回第一次创建的对象即可
class Shopping:
    instance = None #记录创建的对象,None说明是第一次创建对象
    def __new__(cls, *args, **kwargs):
        #第一次调用new方法,创建对象并记录
        #第2-n次调用new方式时,不创建对象,而是直接放回记录的对象

        #判断是否是第一次创建对象
        if cls.instance==None:
            cls.instance = object.__new__(cls)
            return cls.instance
        else: #不是第一次创建对象
            return cls.instance

shop1 = Shopping()
shop2 = Shopping()
print(shop1,shop2)

简写

class Shopping:
    def __new__(cls, *args, **kwargs):
        #第一次调用new方法,创建对象并记录
        #第2-n次调用new方式时,不创建对象,而是直接放回记录的对象

        #判断是否是第一次创建对象,判断是否有instance属性
        if not hasattr(cls,"instance"):
            cls.instance = object.__new__(cls)
        return cls.instance

shop1 = Shopping()
shop2 = Shopping()
print(shop1,shop2)

返回文章目录

你可能感兴趣的:(Python)