简体   繁体   中英

Python - Can I import variables from another file as class variables?

I am trying to find a way to import variables ( dicts) from a file, which will be used inside as class , as class variables. Since I can't use from myVarFile import * inside a class, only at the module level, how would I import them as class variables

eg

from myVarFile import *


class myClass():

    #class variables here
    #should be the data from imported files
    print someImportedVariable

    def __init__(self):
        #init here

    def someClassFunction(self):
       #needs to access class variables
       self.someImportedVariable

As a test I have tried assigning 'global' to all the variables in myVarFile, and adding global variable names inside the class, this works at the class level. But I cannot get any methods to work at all, eg

class myClass():

    #class variables here
    #should be the data from imported files
    global someImportedVariable
    print someImportedVariable
    #this works

    def __init__(self):
        #init here

    def someClassFunction(self):
       #needs to access class variables
       self.someImportedVariable
       #this does not

I wanted to avoid having to globally declare all the variables in each class method, that seems wrong.

Do methods inherit the class variables if they are globally declared from an imported file ?

You can always add attributes to a class outside of the class body:

from module import *

class Bar:
    pass

Bar.foo = foo

or you could just import the name without the * syntax:

class Bar:
    from module import foo

Importing an object is basically an assignment; import name or from module import name sets name in the current namespace.

If you must take all the names from another module and put them in a class, consider putting the class in that module . At the very least, you can put a base class in the module that has all those names you want as attributes, and your new class can inherit it.

So, in the base module:

class BaseName:
    attribute1 = ...
    attribute2 = ...

That's just one indentation level added to what you have now, then in your other module:

from base_module import BaseName

class DerivedClass(BaseName):
    def method(self):
        # do something with self.attribute1, self.attribute2, etc.

If that's not an option, copy the namespace:

import module

class Bar:
    pass

# from module import * takes the names listed in module.__all__, or if that's
# missing, all names in the namespace that do not start with an underscore
_mod_namespace = vars(module)
_names = _mod_namespace.get('__all__', (n for n in _mod_namespace if n[:1] != '_'))
for _name in _names:
    setattr(Bar, _name, _mod_namespace[_name])
del _mod_namespace, _name, _names

Demo:

>>> from string import ascii_letters
>>> class Foo:
...     pass
...
>>> Foo.ascii_letters = ascii_letters
>>> Foo.ascii_letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> class Bar:
...     from string import digits
...
>>> Bar.digits
'0123456789'
>>> import string
>>> string.__all__
['ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable', 'punctuation', 'whitespace', 'Formatter', 'Template']
>>> class Bar:
...     pass
...
>>> before = set(dir(Bar))
>>> _mod_namespace = vars(string)
>>> _names = _mod_namespace.get('__all__', (n for n in _mod_namespace if n[:1] != '_'))
>>> for _name in _names:
...     setattr(Bar, _name, _mod_namespace[_name])
...
>>> [name for name in dir(Bar) if name not in before]
['Formatter', 'Template', 'ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable', 'punctuation', 'whitespace']
>>> Bar.hexdigits
'0123456789abcdefABCDEF'
>>> Bar.punctuation
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'

However , if all you need to do is 'read' the value from your methods, you could just reference globals, you don't have to make such objects class attributes. Just remove the self. prefix from such names, and your code will work just fine.

Sure!

If you have a file source.py with a class like such:

class Animals:
   dogs = ['ralph', 'alex']

and another file import_test.py , you can do this:

class AnimalsTester: 
    from source import Animals

    print Animals.dogs

print AnimalsTester.Animals.dogs

Just make sure they are on the same directory level to keep it simple

In the end I've used the following :

inside the myVarFile.py

someDict = {some contents}
someVar = 'test'

inside the main.py

import myVarFile
class someClass ():
   def someMethod ():
          print myVarFile.someDict

So I avoid having to use class objects at all, and simply prefix the variable with the imported module name . This is clean as I can debug which module the variable is from, and avoid namespace clashes ( especially if I had multiple data modules to import )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM