Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException
вообще.
См. также: A хороший список лучших практик
Я бы добавил, очень важно, хорошо использовать модификатор final
. Использование "окончательной" модификатор, когда это применимо в Java
Сводка:
final
для обеспечения хорошей инициализации. @NotNull
и @Nullable
if("knownObject".equals(unknownObject)
valueOf()
поверх toString (). StringUtils
StringUtils.isEmpty(null)
. Намного более опрятный способ получить 'альтернативных конструкторов' состоит в том, чтобы использовать classmethods. Например:
>>> class MyData:
... def __init__(self, data):
... "Initialize MyData from a sequence"
... self.data = data
...
... @classmethod
... def fromfilename(cls, filename):
... "Initialize MyData from a file"
... data = open(filename).readlines()
... return cls(data)
...
... @classmethod
... def fromdict(cls, datadict):
... "Initialize MyData from a dict's items"
... return cls(datadict.items())
...
>>> MyData([1, 2, 3]).data
[1, 2, 3]
>>> MyData.fromfilename("/tmp/foobar").data
['foo\n', 'bar\n', 'baz\n']
>>> MyData.fromdict({"spam": "ham"}).data
[('spam', 'ham')]
причина, это более опрятно, состоит в том, что нет сомнения, что о том, какой тип ожидается, и Вы не вынуждены предположить то, что вызывающая сторона намеревалась для Вас сделать с типом данных, который это дало Вам. Проблема с isinstance(x, basestring)
состоит в том, что нет никакого способа для вызывающей стороны сказать Вам, например, что даже при том, что тип не является basestring, необходимо рассматривать его как строку (и не другая последовательность.) И возможно вызывающая сторона хотела бы использовать тот же тип в различных целях, иногда как единственный объект, и иногда как последовательность объектов. Быть явным устраняет все сомнение и приводит к большему количеству устойчивого и более ясного кода.
Превосходный вопрос. Я занялся этой проблемой также, и в то время как я соглашаюсь, что "фабрики" (конструкторы метода класса) являются хорошим методом, я хотел бы предложить другого, которого я также нашел очень полезными:
Вот образец (это read
, метод и не конструктор, но идея является тем же):
def read(self, str=None, filename=None, addr=0):
""" Read binary data and return a store object. The data
store is also saved in the interal 'data' attribute.
The data can either be taken from a string (str
argument) or a file (provide a filename, which will
be read in binary mode). If both are provided, the str
will be used. If neither is provided, an ArgumentError
is raised.
"""
if str is None:
if filename is None:
raise ArgumentError('Please supply a string or a filename')
file = open(filename, 'rb')
str = file.read()
file.close()
...
... # rest of code
ключевая идея, здесь использует превосходную поддержку Python параметров, передаваемых по имени для реализации этого. Теперь, если я хочу считать данные из файла, я говорю:
obj.read(filename="blob.txt")
И считать его из строки, я говорю:
obj.read(str="\x34\x55")
Этот путь у пользователя есть просто отдельный метод звонить. Обработка его внутри, как Вы видели, не чрезмерно сложна
Лучший путь состоял бы в том, чтобы использовать isinstance и преобразование типов. Если я понимаю Вас правильный, Вы хотите это:
def __init__ (self, filename):
if isinstance (filename, basestring):
# filename is a string
else:
# try to convert to a list
self.path = list (filename)
Необходимо использовать isinstance
isinstance(...)
isinstance(object, class-or-type-or-tuple) -> bool
Return whether an object is an instance of a class or of a subclass thereof.
With a type as second argument, return whether that is the object's type.
The form using a tuple, isinstance(x, (A, B, ...)), is a shortcut for
isinstance(x, A) or isinstance(x, B) or ... (etc.).
Вы, вероятно, хотите isinstance
встроенная функция:
self.data = data if isinstance(data, list) else self.parse(data)
Хорошо, большой. Я просто бросил вместе этот пример с кортежем, не имя файла, но это легко. Спасибо все.
class MyData:
def __init__(self, data):
self.myList = []
if isinstance(data, tuple):
for i in data:
self.myList.append(i)
else:
self.myList = data
def GetData(self):
print self.myList
= [1,2]
b = (2,3)
c = MyData (a)
d = MyData (b)
c. GetData ()
d. GetData ()
[1, 2]
[2, 3]