a reflective object-oriented python - framework principle - introducing dynamic - metaclasses - custom class - Singleton - Project Life Cycle -05

Reflection reflect

Reflex (reflect) actually introspection, self-examination of the meaning of

Reflection: refers to the detection of an object can be provided, modify, increase the capacity of their own attributes

We need to detect the reflection properties of the class, calling them to the design of the frame

According to four functions reflecting

The four built-in function is normal, there is no double underline, there is no difference between print and so on

# hasattr  getattr  setattr  delattr
class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender


p = Person('jack', 16, 'man')
print(p.name)
# jack


# hasattr  # 判断某个对象中是否存在某个属性
if hasattr(p, 'age'):
    # getattr  # 从对象中取出值,第三个位置默认值,不存在时返回默认值
    print(getattr(p, 'age', None))
    # 16
    # setattr  # 为对象添加、修改新的属性
    print(setattr(p, 'name', 'jackson'))
    # None
    print(getattr(p, 'name'))
    # jackson
    print(setattr(p, 'school', 'oldboy'))
    # None
    print(getattr(p, 'school'))
    # oldboy
    # delattr  # 为对象删除属性
    delattr(p, 'school')
    # print(getattr(p, 'school'))  # 直接报错,AttributeError: 'Person' object has no attribute 'school'

Reflecting usage scenarios

Reflection of the fact that the property additions and deletions to change search, but if you use the built-in direct __dict__to writing, grammar cumbersome, difficult to understand; Another major problem is that if the object did not write, but the other party, I have to determining whether the object is to meet the demand, that is, whether I needed properties and methods

"""
反射被称为框架的基石,为什么?
    因为框架的设计者,不可能提前知道你的对象到底是怎么设计的
    所以你提供给框架的对象 必须通过判断验证之后才能正常使用
    判断验证就是反射要做的事情,
    当然通过__dict__也是可以实现的, 其实这些方法也就是对__dict__的操作进行了封装
"""

Simple framework code

File code execution

myframework.pyCode

# myframework.py
"""
需求:要实现一个用于处理用户的终端指令的小框架
    框架就是已经实现了最基础的构架,就是所有项目都一样的部分
"""
from libs import plugins


# 框架已经实现的部分
def run(plugin):
    while True:
        cmd = input("请输入指令:")
        if cmd == "exit":
            break
        # 因为无法确定框架使用者是否传入正确的对象所以需要使用反射来检测
        # 判断对象是否具备处理这个指令的方法
        if hasattr(plugin,cmd):
            # 取出对应方法方法
            func = getattr(plugin,cmd)
            func() # 执行方法处理指令
        else:
            print("该指令不受支持...")
    print("see you la la!")


# 创建一个插件对象 调用框架来使用它
# wincmd = plugins.WinCMD()
# 框架之外的部分就由自定义对象来完成
linux = plugins.LinuxCMD()
run(linux)

plugins Code

libs/plugins.pyCode

# libs/plugins.py
class WinCMD:

    def cd(self):
        print("wincmd 切换目录....")

    def delete(self):
        print("wincmd 要不要删库跑路?")

    def dir(self):
        print("wincmd 列出所有文件....")

class LinuxCMD:

    def cd(self):
        print("Linuxcmd 切换目录....")

    def rm(self):
        print("Linuxcmd 要不要删库跑路?")

    def ls(self):
        print("Linuxcmd 列出所有文件....")

Dynamic Import

The frame code, written dead, which fixed the class, which is unreasonable, because no way of knowing in advance the other classes where and what type is called , so we should provide a framework for the user's profile, ask the information such as the configuration file, then the framework of their own to load the required modules

Dynamic Import: do not need to know ahead of the class and told to find their own path can

The last ride framework code:

myframework.pyCode

# myframework.py
from conf import settings
import importlib  # 1.动态导入模块

# 框架已经实现的部分
def run(plugin):
    while True:
        cmd = input("请输入指令:")
        if cmd == "exit":
            break
        # 因为无法确定框架使用者是否传入正确的对象所以需要使用反射来检测
        # 判断对象是否具备处理这个指令的方法
        if hasattr(plugin,cmd):
            # 取出对应方法方法
            func = getattr(plugin,cmd)
            func() # 执行方法处理指令
        else:
            print("该指令不受支持...")
    print("see you la la!")


# 框架 得根据配置文件拿到需要的类
path = settings.CLASS_PATH
# 从配置中单独拿出来 模块路径和 类名称
module_path, class_name = path.rsplit(".", 1)
# 2.拿到并导入模块
mk = importlib.import_module(module_path)
# 拿到类
cls = getattr(mk,class_name)
# 用类实例化出对象
obj = cls()
# 调用框架
run(obj)

libs/plugins.pyCode

# libs/plugins.py
class WinCMD:

    def cd(self):
        print("wincmd 切换目录....")

    def delete(self):
        print("wincmd 要不要删库跑路?")

    def dir(self):
        print("wincmd 列出所有文件....")

class LinuxCMD:

    def cd(self):
        print("Linuxcmd 切换目录....")

    def rm(self):
        print("Linuxcmd 要不要删库跑路?")

    def ls(self):
        print("Linuxcmd 列出所有文件....")

conf/settings.pyfile

# conf/settings.py
CLASS_PATH = "libs.plugins.WinCMD"

In this way, the framework and implementation of the code will completely decoupled, leaving only the configuration file

Metaclass metaclass

Yuan class is used to create a class of class

In python, all things are subject, of course, the object class

Inference: the object is generated by instantiating the class, if the class is an object, it certainly class object instantiated by another class is generated

class Person:
    pass


p = Person()
print(type(p), type(Person), type(object))
# <class '__main__.Person'> <class 'type'> <class 'type'>
# Person类是通过type类实例化产生的(object类内部是由C语言实现的)

# 直接调用type类来产生类对象(默认情况下所有类的元类都是type)
class Student:
    pass


print(type(Student))
# <class 'type'>

A class of basic components

  1. Name (character type) class
  2. Class parent who (a tuple or list)
  3. Class name space (dictionary)
cls_obj = type("ClassDog", (), {})
print(cls_obj)
# <class '__main__.ClassDog'>


class Dog:
    pass


print(Dog)
# <class '__main__.Dog'>

Learning Meta categories

Objective: can be highly custom class name of a class, for example, the control must be written in large hump manner

Classes are objects, also have their own class

Our demand is to create a class object to do some limitations

  • I thought initialization method, as long as we find a class object class (metaclass), which covers the __init__method can achieve demand

  • Of course, we can not modify the source code, so it should be inherited typeto write your own metaclass, while covering __init__to complete the requirements

'''
只要继承了type, 那么这个类就变成了一个元类

'''


class MyType(type):  # 定义一个元类
    def __init__(self, cls_name, bases, dict):
        print(cls_name, bases, dict)
        # Pig () {'__module__': '__main__', '__qualname__': 'Pig'}
        if not cls_name.istitle():
            raise Exception("好好写类名!")
        super().__init__(cls_name, bases, dict)

    pass


# class pig(metaclass=MyType):  # 为Pig类指定了元类为MyType
    # 直接报错,Exception: 好好写类名!
class Pig(metaclass=MyType):

    pass


# # MyType("pig", (), {})  # Exception: 好好写类名!
print(MyType("Pig", (), {}))
# <class '__main__.Pig'>

__call__

call method metaclasses

# 当你调用类对象时,会自动执行元类中的__call__方法,并将这个类作为第一个参数传入,以及后面的一堆参数

# 覆盖元类中的call之后,这个类就无法产生对象对象无法实例化,必须调用super().__call__()来完成对象的创建并返回其返回值

__call__ 与 __init__Usage scenarios:

  1. Want to control object creation process with__call__

  2. Want to control the process of creating classes with__init__

'''
需求:想要把对象的所有属性变成大写
'''
class MyType(type):
    def __call__(self, *args, **kwargs):
        new_args = [item.upper() for item in args]
        return super().__call__(*new_args, **kwargs)


class Person(metaclass=MyType):  # ---> Person = MyType("Person", (), {})
    def __init__(self, name):
        self.name = name


p = Person('jack')
print(p.name)
# JACK
# 要求创建对象时必须以关键字传参
#   覆盖元类的__call__
#   判断有没有传非关键字参数,有就不行
class MyMeta(type):
    # def __call__(self, *args, **kwargs):
    #     obj = object.__new__(self)
    #     self.__init__(obj, *args, **kwargs)
    #     return obj

    def __call__(self, *args, **kwargs):
        if args:
            raise Exception("非法传参(只能以关键字的形式传参!)")
        return super().__call__(*args, **kwargs)


class MyClass(metaclass=MyMeta):
    def __init__(self, name):
        self.name = name


# my_class_obj = MyClass('123')
# # 报错Exception: 非法传参(只能以关键字的形式传参!)
my_class_obj = MyClass(name='123')
print(my_class_obj)
# <__main__.MyClass object at 0x000002161DD187B8>

Note: Once the covering __call__must call the parent class __call__method to generate the object and return the object

Supplementary __new__Methods

When you want to create a class object ( 类 + ()) will be executed first yuan class __new__method to get an empty object, and then will automatically call the __init__method to initialize the operation of the class

class MyMeta(type):
    # def __call__(self, *args, **kwargs):
    #     obj = object.__new__(self)
    #     self.__init__(obj, *args, **kwargs)
    #     return obj
    pass

Note: If you're covering a __new__method, you must ensure that __new__the method must have a return value, and must be a corresponding class object

class Meta(type):

    def __new__(cls, *args, **kwargs):
        print(cls)  # 元类自己
        print(args)  # 创建类需要的几个参数  类名,基类,名称空间
        print(kwargs)  # 空的
        print("__new__ run")
        # return super().__new__(cls,*args,**kwargs)  # 等同于下面这句
        obj = type.__new__(cls, *args, **kwargs)
        return obj

    def __init__(self, a, b, c):
        super().__init__(a, b, c)
        print("__init__ run")


class A(metaclass=Meta):
    pass


print(A)
# <class '__main__.Meta'>
# ('A', (), {'__module__': '__main__', '__qualname__': 'A'})
# {}
# __new__ run
# __init__ run
# <class '__main__.A'>

Summary:__new__ and __init__can achieve the creation of process control classes, or __init__more simply

Singleton design pattern

'''
设计模式?
    用于解决某种固定问题的套路
    如:MVC、MTV.......

单例:指的是一个类只能产生一个对象,可以节省空间

为什么要单例:
    是为了节省空间,节省资源
    当一个类的所有对象属性全部相同时则没有必要创建多个对象
'''
class Single(type):
    def __call__(self, *args, **kwargs):
        if hasattr(self, 'obj'):  # 判断是否存在已经有了的对象
            return getattr(self, 'obj')  # 有就把那个对象返回

        obj = super().__call__(*args, **kwargs)  # 没有则创建
        print("new 了")
        self.obj = obj  # 并存入类中
        return obj


class Student(metaclass=Single):
    def __init__(self, name):
        self.name = name


class Person(metaclass=Single):
    pass


# 只会创建一个对象
Person()  # 只会执行一次
# new 了
Person()
Person()
Person()
Person()

The project life cycle

demand analysis

Clear user needs, users in the end what kind of program needs, what kind of functions to be achieved, a lot of the time, users are in the obscenity, the logic is incorrect, it is necessary to engineer, face to face communication with the user to determine the user's real needs and realizability requirements, and according to the final demand, resulting in a book project needs analysis

Technology Selection

The project uses to determine what development languages, frameworks, databases, and version, etc.

We need to consider the use of technology framework based on the actual situation of the company, usually do business with the industry's mainstream implementations, such as various versions of the framework, to consider the compatibility of proficiency, prevalence, and engineers

Architecture design projects

For example; database design, project architecture (MVC, MTV, three-tier architecture, etc.) design

As the project developed at once impossible to get away, the latter need to maintain expansion, so good architectural design is important for ongoing maintenance extension

Also, if your idea from the start is not correct, and that the latter is likely to rewrite the entire project overthrow

The project design is of course the sooner the better, but the learning phase, according to some framework to write directly, you will feel very abstract, why should such a design, what good is? Cause a feeling that has not yet begun to write code has forced the ignorant is not so clear first pre design problems, and then find the appropriate solutions

development stage

The project manager will assign tasks to each person, as a background to develop need to provide interface documentation to enable the two sides to develop according to the same protocol, a number of collaborative development tools need to use: git, svn

Project development is actually a relatively short time-consuming phase, provided that the requirements have been specified, the project design is no problem, then write the code book based on needs analysis, companies generally have more engineers, project managers responsible for assigning tasks, each engineers develop complete submit their own code modules, and finally merge together all of the code, the project developed

Project Test

Large companies often have a special test engineers, developers does not mean the completion of this work is over, you need to pay the full test project engineer, some small companies may not have this job, it needs to develop its own engineers to complete the test

On-line deployment

Need to deploy server, install the appropriate environment, the release code, you also need to apply for a domain name server

In the test can be more than a line running through the project, on-line operation means that you can actually run the program on the Internet, in the development phase of the project are generally used LAN environment, ordinary users can not access, you need to project deployed to the server, and then get a public ip for the server, and give the ip binding domain, ie, normal operation of the project so far

Update and maintain

Follow-up will need to add new features or modify various bug, continue to improve projects, iterative version of the update, unfortunately, of course, if the company goes bankrupt, then the life cycle of the project will be over

Guess you like

Origin www.cnblogs.com/suwanbin/p/11272139.html