リフレクションを反映します
レフレックス(反映)実際にはイントロスペクション、の意味の自己検査
リフレクション:物体の検出を指し提供することができ、修正、自分の属性の容量を増やします
私たちは、フレームのデザインにそれらを呼び出して、クラスの反射特性を検出する必要があります
反射4つの機能によれば、
4組み込み関数は、ように、プリントとの間に差がない、ない二重下線がない、正常です
# 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'
利用シナリオを反映
プロパティの追加や削除、検索を変更するという事実を反映していますが、内蔵のダイレクトを使用している場合は__dict__
書き込みを、理解し、面倒難しい文法、もう一つの大きな問題は、オブジェクトが書き、それ以外の当事者しなかった場合、私が持っているということです私はプロパティとメソッドを必要とするかどうか、オブジェクトがあり、需要を満たすためにあるかどうかを判断します
"""
反射被称为框架的基石,为什么?
因为框架的设计者,不可能提前知道你的对象到底是怎么设计的
所以你提供给框架的对象 必须通过判断验证之后才能正常使用
判断验证就是反射要做的事情,
当然通过__dict__也是可以实现的, 其实这些方法也就是对__dict__的操作进行了封装
"""
シンプルなフレームワークコード
ファイルのコードの実行
myframework.py
コード
# 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)
プラグインコード
libs/plugins.py
コード
# 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 列出所有文件....")
ダイナミックインポート
理由は、無理があるクラスは、固定しない死んだ書かれたフレームコード、どこ事前に他のクラスを知る方法とどのようなタイプと呼ばれているので、私たちは、ユーザーのプロファイルのためのフレームワークを提供する必要があり、頼みます情報は、設定ファイルとして、その後、独自のフレームワークは、必要なモジュールをロードします
ダイナミックインポート:先クラスの知っている必要があり、自分の道を見つけるように言わないで行うことができます
最後の乗車フレームワークコード:
myframework.py
コード
# 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.py
コード
# 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.py
ファイル
# conf/settings.py
CLASS_PATH = "libs.plugins.WinCMD"
このように、コードのフレームワークおよび実装が完全にのみ設定ファイルを残して、デカップリングします
メタクラスメタクラス
元のクラスは、クラスのクラスを作成するために使用されます
Pythonでは、すべてのものは、当然のことながら、オブジェクトクラス対象となっています
推論:クラスがオブジェクトである場合、オブジェクトは、クラスをインスタンス化することによって生成され、別のクラスによってインスタンスば確かにクラスのオブジェクトが生成されます
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'>
基本コンポーネントのクラス
- 名前(文字型)クラス
- クラスの親(タプルまたはリスト)
- クラスの名前空間(辞書)
cls_obj = type("ClassDog", (), {})
print(cls_obj)
# <class '__main__.ClassDog'>
class Dog:
pass
print(Dog)
# <class '__main__.Dog'>
メタカテゴリを学びます
目的:クラスの非常にカスタムクラス名を指定することができ、例えば、制御が大きなこぶ状に記述する必要があります
クラスはまた、オブジェクトである、独自のクラスを持っています
私たちの需要があるいくつかの制限を行うには、クラスのオブジェクトを作成します
私がいる限り、我々は見つけるとカバークラスオブジェクトのクラス(メタクラス)、初期化メソッドを考えた
__init__
方法は需要を達成することができますもちろん、私たちは、ソースコードを変更することはできませんので、継承されるべき
type
カバーしながら、独自のメタクラスを書くため__init__
の要件を完了するために、
'''
只要继承了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__方法,并将这个类作为第一个参数传入,以及后面的一堆参数
# 覆盖元类中的call之后,这个类就无法产生对象对象无法实例化,必须调用super().__call__()来完成对象的创建并返回其返回值
__call__ 与 __init__
使用シナリオ:
制御したいオブジェクトの作成プロセスをと
__call__
制御したいクラスを作成するプロセスとを
__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>
注意:カバーは一度__call__
、親クラスを呼び出す必要があります__call__
オブジェクトを生成し、オブジェクトを返すようにする方法を
補足__new__
方法
あなたはクラスオブジェクトを作成したい場合は(类 + ()
)最初の元クラスに実行される__new__
空のオブジェクトを取得する方法を、その後、自動的に呼び出します__init__
クラスの動作を初期化する方法を
class MyMeta(type):
# def __call__(self, *args, **kwargs):
# obj = object.__new__(self)
# self.__init__(obj, *args, **kwargs)
# return obj
pass
注意:あなたがカバーしている場合は__new__
この方法を、あなたがいることを確認する必要があります__new__
メソッドは戻り値を持っている必要があり、対応するクラスのオブジェクトである必要があります
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'>
概要:__new__
および__init__
プロセス制御クラスの作成を達成することができ、または__init__
より簡単に
シングルトンデザインパターン
'''
设计模式?
用于解决某种固定问题的套路
如: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()
プロジェクトのライフサイクル
要件分析
クリアユーザーのニーズ、達成すべき機能のどのようなプログラムのニーズの種類、最終的にはユーザー、多くの時間、ユーザーがわいせつである、ロジックが間違っている、設計する必要があり、利用者の真のニーズを決定するために、ユーザーとのコミュニケーションを対面そして、実現可能性の要件、および最終需要に応じて、本プロジェクトの結果は、分析を必要とします
技術選択
このプロジェクトは、その他どのような開発言語、フレームワーク、データベース、およびバージョンを決定するために使用しています
私たちは、習熟度、有病率、およびエンジニアの互換性を考慮し、通常、そのようなフレームワークの様々なバージョンとして、業界で主流の実装でビジネスを行う企業の実際の状況に基づいて、技術フレームワークの使用を検討する必要があります
アーキテクチャ設計プロジェクト
例えば、データベース設計、プロジェクト・アーキテクチャ(MVC、MTV、3層アーキテクチャ、等)の設計
逃げるために一度は不可能で開発プロジェクトとして、拡張性を維持するために後者の必要性は、とても良い建築デザインは、継続的なメンテナンス延長のために重要です
また、最初からあなたの考えは正しくないこと、および後者は、プロジェクト全体の転覆を書き換える可能性がある場合
プロジェクトのデザインは、あなたが、非常に抽象的に感じます直接書き込むためにいくつかのフレームワークによると、当然のことながら早いほど良いが、学習段階である理由をすべきなデザイン、何が良いのですか?まだ、コードを書くために開始されていない感が原因それほど明確で最初の前の設計上の問題ではない無知を強制し、適切な解決策を見つけました
開発フェーズ
プロジェクトマネージャは、同じプロトコルに従って開発するために、2つの側面を可能にするためのインタフェースのドキュメントを提供する必要性を開発する背景として、共同開発ツールの数は、使用する必要があり、一人一人にタスクを割り当てます:gitの、SVNを
プロジェクト開発は、実際には、比較的短い時間のかかるフェーズで、要件が指定されている、プロジェクトの設計は問題ありませんことを提供し、ニーズの分析に基づいてコードブックを書き、企業は一般的に多くのエンジニアが、タスクの割り当てを担当するプロジェクトマネージャー、それぞれを持っていますエンジニアは、プロジェクトが開発した、独自のコードモジュールを提出し、最終的には一緒にすべてのコードをマージし、完全な開発します
プロジェクトのテスト
大企業は、多くの場合、あなたは完全なテストプロジェクトエンジニアを支払う必要があり、開発者は、この作業の完了が終わったという意味ではありません、特別なテストエンジニアを持って、いくつかの小さな企業がこの仕事を持っていない可能性があり、それがテストを完了するために、独自の技術を開発する必要があります
オンライン展開
サーバーを展開する必要があり、適切な環境、リリースコードをインストールし、あなたはまた、ドメインネームサーバを申請する必要があり
テストでは、オンライン操作は、あなたが実際に一般的にLAN環境を使用している、普通のユーザーがアクセスできないプロジェクトの開発段階では、インターネット上でプログラムを実行できることをプロジェクトを通じて実行されているラインよりも意味することができ、あなたがする必要がありますプロジェクトがサーバーにデプロイし、サーバーのパブリックIPを取得し、これまでのところ、IP結合ドメイン、プロジェクトのすなわち、正常な動作を与えます
更新と維持
フォローアップは、プロジェクト、更新の反復バージョンを改善し続け、様々なバグを新しい機能を追加または変更する必要がありますが、残念ながら、当然のことながら、会社が倒産した場合、その後、プロジェクトのライフサイクルは終わっただろう