如何在 Python 中的方法中访问 class
How to access class within a method in Python
我有一个函数 make_package
返回 class Package
。在另一个文件中,我想导入 class Package
,这样我就可以进行类型检查。我的问题是,如何导入函数内部的 class?
以下不是确切的代码,但结构相似。
# project/package.py
def make_package(ori, dest):
class Package:
origin = ori
destination = dest
def __init__(self, item):
self.item = item
def to_str(self):
return self.origin + '-' + self.destination + ' : ' + self.item
return Package
# project/shipment.py
# Don't know how to import Package from package.py
class Shipment:
def __init__(self, **kwargs):
self.shipment = dict()
for container in kwargs.keys():
self.shipment[container] = list()
for item in kwargs[key]:
if type(item) != Package:
raise TypeError('Item must be packed in Package.')
self.shipment[container].append(item.to_str())
# project/main.py
from .package import make_package
from .shipment import Shipment
us_fr = make_package('US', 'FR')
fr_cn = make_package('FR', 'CN')
shipment = Shipment(container1=[us_fr('item1'), fr_cn('item2')], container2=[us_fr('item3'), fr_cn('item4')])
print(shipment.shipment)
# {
# 'container1' : [
# 'US-FR : item1',
# 'FR-CN' : 'item2'
# ],
# 'container2' : [
# 'US-FR : item3',
# 'FR-CN' : 'item4'
# ]
# }
我知道我可以实现类型检查的一种方法是在 Shipment
中创建一个带有 make_package
的 虚拟 变量,然后将 type(item)
与type(dummy)
。然而,它似乎更像是一个黑客。请问有没有更好的办法?
无法从函数外部 "import" 您的 class,因为实际上没有 Package
类型。每次调用 make_package()
时,都会 创建一个新类型 ,它恰好与所有其他 Package
类型同名。然而,它仍然是一个独特的类型,所以 它永远不会与另一个 Package
类型 比较,即使 origin
和 destination
相同.
您可以使所有 Package
类型继承自 "marker" class,然后使用 isinstance
检查项目是否为包:
# project/package.py
class PackageMarker:
pass
def make_package(ori, dest):
class Package(PackageMarker):
... # Package body here
return Package
# project/shipment.py
class Shipment:
def __init__(self, **kwargs):
self.shipment = dict()
for container in kwargs.keys():
self.shipment[container] = list()
for item in kwargs[key]:
if not isinstance(item, PackageMarker):
raise TypeError('Item must be packed in Package.')
self.shipment[container].append(item.to_str())
在我看来,您使用此工厂函数创建 classes 的方式令人困惑,但也许我只是需要更多上下文来了解您为什么要这样做。
如果你想要我对如何重构它的意见,我会删除工厂函数,然后做这样的事情:
# project/package.py
class Package:
def __init__(self, route, item):
self.route = route
self.item = item
def to_str(self):
return self.route.to_str() + ' : ' + self.item
# project/route.py
class Route:
def __init__(self, origin, destination):
self.origin = origin
self.destination = destination
def to_str(self):
return self.origin + ' - ' + self.destination
# project/shipment.py
from .package import Package
class Shipment:
def __init__(self, **kwargs):
self.shipment = dict()
for container in kwargs.keys():
self.shipment[container] = list()
for item in kwargs[key]:
if not isinstance(item, Package):
raise TypeError('Item must be packed in Package.')
self.shipment[container].append(item.to_str())
# project/main.py
from .package import Package
from .route import Route
from .shipment import Shipment
us_fr = Route('US', 'FR')
fr_cn = Route('FR', 'CN')
shipment = Shipment(
container1=[Package(us_fr, 'item1'), Package(fr_cn, 'item2')],
container2=[Package(us_fr, 'item3'), Package(fr_cn, 'item4')]
)
我有一个函数 make_package
返回 class Package
。在另一个文件中,我想导入 class Package
,这样我就可以进行类型检查。我的问题是,如何导入函数内部的 class?
以下不是确切的代码,但结构相似。
# project/package.py
def make_package(ori, dest):
class Package:
origin = ori
destination = dest
def __init__(self, item):
self.item = item
def to_str(self):
return self.origin + '-' + self.destination + ' : ' + self.item
return Package
# project/shipment.py
# Don't know how to import Package from package.py
class Shipment:
def __init__(self, **kwargs):
self.shipment = dict()
for container in kwargs.keys():
self.shipment[container] = list()
for item in kwargs[key]:
if type(item) != Package:
raise TypeError('Item must be packed in Package.')
self.shipment[container].append(item.to_str())
# project/main.py
from .package import make_package
from .shipment import Shipment
us_fr = make_package('US', 'FR')
fr_cn = make_package('FR', 'CN')
shipment = Shipment(container1=[us_fr('item1'), fr_cn('item2')], container2=[us_fr('item3'), fr_cn('item4')])
print(shipment.shipment)
# {
# 'container1' : [
# 'US-FR : item1',
# 'FR-CN' : 'item2'
# ],
# 'container2' : [
# 'US-FR : item3',
# 'FR-CN' : 'item4'
# ]
# }
我知道我可以实现类型检查的一种方法是在 Shipment
中创建一个带有 make_package
的 虚拟 变量,然后将 type(item)
与type(dummy)
。然而,它似乎更像是一个黑客。请问有没有更好的办法?
无法从函数外部 "import" 您的 class,因为实际上没有 Package
类型。每次调用 make_package()
时,都会 创建一个新类型 ,它恰好与所有其他 Package
类型同名。然而,它仍然是一个独特的类型,所以 它永远不会与另一个 Package
类型 比较,即使 origin
和 destination
相同.
您可以使所有 Package
类型继承自 "marker" class,然后使用 isinstance
检查项目是否为包:
# project/package.py
class PackageMarker:
pass
def make_package(ori, dest):
class Package(PackageMarker):
... # Package body here
return Package
# project/shipment.py
class Shipment:
def __init__(self, **kwargs):
self.shipment = dict()
for container in kwargs.keys():
self.shipment[container] = list()
for item in kwargs[key]:
if not isinstance(item, PackageMarker):
raise TypeError('Item must be packed in Package.')
self.shipment[container].append(item.to_str())
在我看来,您使用此工厂函数创建 classes 的方式令人困惑,但也许我只是需要更多上下文来了解您为什么要这样做。
如果你想要我对如何重构它的意见,我会删除工厂函数,然后做这样的事情:
# project/package.py
class Package:
def __init__(self, route, item):
self.route = route
self.item = item
def to_str(self):
return self.route.to_str() + ' : ' + self.item
# project/route.py
class Route:
def __init__(self, origin, destination):
self.origin = origin
self.destination = destination
def to_str(self):
return self.origin + ' - ' + self.destination
# project/shipment.py
from .package import Package
class Shipment:
def __init__(self, **kwargs):
self.shipment = dict()
for container in kwargs.keys():
self.shipment[container] = list()
for item in kwargs[key]:
if not isinstance(item, Package):
raise TypeError('Item must be packed in Package.')
self.shipment[container].append(item.to_str())
# project/main.py
from .package import Package
from .route import Route
from .shipment import Shipment
us_fr = Route('US', 'FR')
fr_cn = Route('FR', 'CN')
shipment = Shipment(
container1=[Package(us_fr, 'item1'), Package(fr_cn, 'item2')],
container2=[Package(us_fr, 'item3'), Package(fr_cn, 'item4')]
)