在方法之外使用 super() 获取父类中的私有属性

问题描述

我有一个带有私有常量 _BAR = object() 的类。

在子类中,在方法之外(无法访问 self),我想引用 _BAR

这是一个人为的例子:

class Foo:
    _BAR = object()

    def __init__(self,bar: object = _BAR):
        ...

class DFoo(Foo):
    """Child class where I want to access private class variable from parent."""

    def __init__(self,baz: object = super()._BAR):
        super().__init__(baz)

不幸的是,这不起作用。一个错误RuntimeError: super(): no arguments

有没有办法在方法之外使用 super 来获取父类属性


解决方法是使用 Foo._BAR,我想知道是否可以使用 super解决这个问题。

解决方法

import { GetStaticPropsContext,GetStaticPropsResult,GetStaticPathsContext,InferGetStaticPropsType } from 'next'; import { initializeApollo,addApolloState } from '@/lib/apollo'; import { DynamicNavDocument,DynamicNavQueryVariables,DynamicNavQuery,WordpressMenuNodeIdTypeEnum } from '@/graphql/generated/graphql'; import { AppLayout } from '@/components/Layout'; import { useRouter } from 'next/router'; import { Container,Fallback } from '@/components/UI'; import useSWR from 'swr'; import { fetcherGallery } from '@/lib/swr-fetcher'; import { Gallery } from '@/types/booksy/media'; import { Configuration,Fetcher } from 'swr/dist/types'; import { getLatestBooksyPhotos,getBooksyPhotoById } from '@/lib/booksy'; import Image,{ ImageLoaderProps } from 'next/image'; import { parseUrl } from '@/lib/helpers'; export async function getStaticPaths({ locales }: GetStaticPathsContext): Promise<{ paths: string[]; fallback: false; }> { const data: Response = await getLatestBooksyPhotos(); const pathsData: Gallery = await data.json(); return { paths: locales ? locales.reduce<string[]>((arr,locale) => { pathsData.images.forEach(imageId => { arr.push(`/${locale}/gallery/${imageId.image_id}`); }); return arr; },[]) : pathsData?.images.map( imageId => `/gallery/${imageId.image_id}` ),fallback: false }; } export async function getStaticProps<P>( ctx: GetStaticPropsContext ): Promise< GetStaticPropsResult< P & { Header: DynamicNavQuery['Header']; Footer: DynamicNavQuery['Footer']; initDataImage: Partial< Configuration<Gallery,any,Fetcher<Gallery>> >; id: string; } > > { const apolloClient = initializeApollo({ headers: ctx.params ?? {} }); await apolloClient.query< DynamicNavQuery,DynamicNavQueryVariables >({ notifyOnNetworkStatusChange: true,fetchPolicy: 'cache-first',query: DynamicNavDocument,variables: { idHead: 'Header',idTypeHead: WordpressMenuNodeIdTypeEnum.NAME,idTypeFoot: WordpressMenuNodeIdTypeEnum.NAME,idFoot: 'Footer' } }); const id = ctx?.params ? (ctx.params.id as string) : '21177790'; const initDataGallery = await getBooksyPhotoById(id); const initDataImage: Gallery = await initDataGallery.json(); return addApolloState(apolloClient,{ props: { initDataImage,id },revalidate: 600 }); } export default function GalleryById< T extends typeof getStaticProps >({ Header,Footer,initDataImage,id }: InferGetStaticPropsType<T>) { const router = useRouter(); const parsedId = router.query ? (router.query.id as string) : ''; const { data } = useSWR<Gallery>( `/api/booksy-image-by-id/?category=biz_photo&image_id=${ id ? id : parsedId }`,fetcherGallery,initDataImage ); const booksyImageLoader = ({ src,width,quality }: ImageLoaderProps) => { return `${src}?w=${width}&q=${quality || 75}`; }; const targetThumbnail = data?.images[0].thumbnails['640,0-hr'] .url ? data.images[0].thumbnails['640,0-hr'].url : data?.images[0].image ? data.images[0].image : ''; const thumbnailDecoded = decodeURI(targetThumbnail ?? ''); const fragmentThumbnailURI = parseUrl(thumbnailDecoded ?? ''); const thumbnailReconstructed = `${fragmentThumbnailURI?.baseUrl.concat( fragmentThumbnailURI.pathname )} ` ?? ''; return ( <> {router.isFallback ? ( <Fallback /> ) : ( <AppLayout Header={Header} Footer={Footer} title={`${data?.images[0].image_id ?? parsedId}`} > <Container clean className='my-16 max-w-5xl mx-auto block rounded-xl shadow-cardHover' > {data && data.images ? ( <Image className='rounded-xl object-cover' src={ thumbnailReconstructed !== '' ? thumbnailReconstructed : '/doge-404.jpg' } loader={booksyImageLoader} width='1280' height='1294' priority quality={100} layout='responsive' /> ) : ( <Fallback /> )} </Container> </AppLayout> )} </> ); } 中,您不能在不引用 DFoo 的情况下引用 Foo._BAR。 Python 变量在局部、封闭、全局和内置作用域中搜索(按此顺序,这是所谓的 LEGB 规则)并且 Foo 不存在于其中任何一个。

让我们忽略显式 _BAR

此外,它会被继承:Foo._BAR 将首先在 DFoo._BAR 中查找,如果找不到,则在 DFoo 中查找。

还有什么其他方法可以获取 Foo 引用? FooFoo 的基类。我们可以使用这种关系吗?是和否。执行时是,定义时否。

问题是在定义 DFoo 时,它还不存在。我们没有开始遵循继承链的起点。这排除了 DFoo 行和类属性 DFoo 中的间接引用(Foo -> def method(self,....):)。

可以使用类装饰器来解决此限制。定义类然后修改:

_DBAR = _BAR

使用元类可以达到类似的效果。

获取对 def deco(cls): cls._BAR = cls.__mro__[1]._BAR * 2 # __mro__[0] is the class itself return cls class Foo: _BAR = 10 @deco class DFoo(Foo): pass print(Foo._BAR,DFoo._BAR) # 10 20 的引用的最后一个选项是在执行时。我们有对象Foo,它的类型是self,它的父类型是DFoo,并且存在Foo。众所周知的 _BAR 是获取父级的快捷方式。

为简单起见,我只假设了一个基类。如果有多个基类,super() 只返回其中之一。示例类装饰器也做同样的事情。要了解多个碱基如何排序为一个序列,请参阅 MRO 的工作原理(方法解析顺序)。

我的最后一个想法是,我无法想出一个需要问题中的访问权限的用例。

,

简短的回答:你不能!

我不会详细介绍 "super",但让我们看看如何调用 super:

1- 没有参数,正如文档所说:

零参数形式仅在类定义中有效,因为 编译器填写必要的详细信息以正确检索 正在定义的类,以及访问当前实例 普通方法。

(除非被调用,否则函数/方法的主体不会被执行,所以如果 DFoo 尚不存在也没有问题)

2- 有两个论点,上面提到的那些必要细节是什么?一个“类型”和一个“实例”:

我们不能在这里传递 DFoo 的“实例”和“类型”。第一个是因为它不在方法内部,所以我们无法访问 instance(self)。第二个是 DFoo 本身。当 DFoo 类的主体被执行时,没有对 DFoo 的引用,它还不存在。类的主体在作为字典的命名空间内执行。 之后,使用该填充的字典创建了一个 type 类型的新实例,此处名为 DFoo,并将其添加到全局命名空间中。这就是 class 关键字在简单形式中的大致作用。

3-另外两个都是类型的参数:

如果第二个参数是类型,则 issubclass(type2,type) 必须是 真的

上面提到的关于访问 DFoo 的相同原因。

4- 还有另一种形式可以用一个参数调用 super,它是一个单一的“类型”:

如果省略第二个参数,则返回的超级对象为 未绑定。

再次访问上述 DFoo 类型的相同原因,没有任何改变。只是为了记录而添加。这些是我们调用 super 的方式。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...