Комментарий с верхним голосованием в верхнем ответе предполагает, что подход Мартина Анкерла лучше, чем случайные шестнадцатеричные числа, и хотя я не улучшил методологию Анкерла, я успешно перевел его на JavaScript. Я решил опубликовать дополнительный ответ на этот и так мегабаритный SO поток, потому что в верхнем ответе есть еще один комментарий, связанный с Gist с реализацией JS логики Ankerl, и эта ссылка не работает (404). Если бы у меня была репутация, я бы просто прокомментировал созданную мной ссылку jsbin.
// adapted from
// http://jsfiddle.net/Mottie/xcqpF/1/light/
const rgb2hex = (rgb) => {
return (rgb && rgb.length === 3) ? "#" +
("0" + parseInt(rgb[0],10).toString(16)).slice(-2) +
("0" + parseInt(rgb[1],10).toString(16)).slice(-2) +
("0" + parseInt(rgb[2],10).toString(16)).slice(-2) : '';
}
// next two methods converted from Ruby to JS
// soured from http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
// # HSV values in [0..1[
// # returns [r, g, b] values from 0 to 255
const hsv_to_rgb = (h, s, v) => {
const h_i = Math.floor(h*6)
const f = h*6 - h_i
const p = v * (1 - s)
const q = v * (1 - (f * s))
const t = v * (1 - (1 - f) * s)
let r, g, b
switch(h_i){
case(0):
[r, g, b] = [v, t, p]
break
case(1):
[r, g, b] = [q, v, p]
break
case(2):
[r, g, b] = [p, v, t]
break
case(3):
[r, g, b] = [p, q, v]
break
case(4):
[r, g, b] = [t, p, v]
break
case(5):
[r, g, b] = [v, p, q]
break
}
return [Math.floor(r * 256), Math.floor(g * 256), Math.floor(b * 256)]
}
// # use golden ratio
const golden_ratio_conjugate = 0.618033988749895
let h = Math.random() // # use random start value
const gen_hex = (numberOfColors) => {
const colorArray = []
while (numberOfColors > 0) {
h += golden_ratio_conjugate
h %= 1
colorArray.push(rgb2hex(hsv_to_rgb(h, 0.99, 0.99)))
numberOfColors -= 1
}
console.log(colorArray)
return colorArray
}
gen_hex(100)
Я не думаю, что то, что вы хотите, возможно напрямую в Python.
Вы можете, однако, попробовать одно из следующего:
to_import_from.py
добавьте туда несгенерированный материал. Сюда,
все методы находятся в одном и том же определении класса. to_import_from.py
содержит определение базового класса, которое класс Instrument
наследуется. Другими словами, в to_import_from.py
:
class InstrumentBase(object):
def external_method(self, arg1, arg2):
if self.flag:
...
, а затем в main_module.py
:
import to_import_from
class Instrument(to_import_from.InstrumentBase):
def __init__(self):
...
Люди, кажется, слишком задумываются над этим. Методы - это просто локальные переменные со значением функции в области построения класса. Итак, следующее работает нормально:
class Instrument(Object):
# load external methods
from to_import_from import *
def __init__(self):
self.flag = True
def direct_method(self,arg1):
self.external_method(arg1, arg2)
Это проще, чем вы думаете:
class Instrument(Object):
def __init__(self):
self.flag = True
def direct_method(self,arg1):
self.external_method(arg1, arg2)
import to_import_from
Instrument.external_method = to_import_from.external_method
Готово!
Хотя создание машинно-сгенерированного кода для генерации определения класса и создания на его основе подклассов было бы более изящным решением.
вы можете сделать это с помощью метода __ getattr __
external.py
def external_function(arg):
print("external", arg)
main.py:
import external
class Instrument(object):
def __getattr__(self, name):
if hasattr(external, name):
return getattr(external, name)
else:
return Object.__getattr__(self, name)
def direct_method(self, arg):
print("internal", arg)
i = Instrument()
i.direct_method("foo")
i.external_function("foo")
I Мне очень жаль, что это что-то вроде ответа «Вы не должны забивать гвозди в стену» , но вы упускаете суть определений классов python. Вам лучше поместить класс со всеми его методами в отдельный файл python и в ваш main_module.py
do
from instrument import Instrument
. Если вы планируете использовать методы для нескольких классов, вам следует рассмотреть возможность создания подклассов. В вашем случае файл, сгенерированный машиной, может содержать базовый класс, который Instrument
наследует от.
Наконец, дайте вашему классу хорошую строку документации, которая объясняет API его пользователю, так что нет необходимости в "заголовочный файл", используемый в качестве обзора вашего класса.
Вот моя попытка. Я думаю, что более удачный подход может быть сделан с помощью метаклассов ...
to_import_from.py:
def external_method(self, arg1, arg2):
if self.flag:
print "flag is set"
else :
print "flag is not set"
instrument.py:
import imp
import os
import inspect
import new
import pdb
class MethodImporter(object) :
def __init__(self, path_to_module) :
self.load_module(path_to_module)
def load_module(self, path_to_module) :
name = os.path.basename(path_to_module)
module_file = file(path_to_module,"r")
self.module = imp.load_module(name, module_file , path_to_module, ('','r',imp.PY_SOURCE))
print "Module %s imported" % self.module
for method_name, method_object in inspect.getmembers(self.module, inspect.isfunction) :
print "adding method %s to %s" % (method_name, self)
setattr(self, method_name, new.instancemethod(method_object, self, self.__class__))
class Instrument(MethodImporter):
def __init__(self):
super(Instrument,self).__init__("./to_import_from.py")
self.flag = True
def direct_method(self,arg1):
self.external_method(arg1, arg2)
при запуске этого кода
arg1, arg2 = 1, 2
instr = Instrument()
instr.direct_method(arg1)
instr.external_method(arg1, arg2)
вот результат:
Module <module 'to_import_from.py' from './to_import_from.pyc'> imported
adding method external_method to <__main__.Instrument object at 0x2ddeb0>
flag is set
flag is set
Технически да, это возможно, но решение этой проблемы таким образом не совсем идиоматический Python, и, вероятно, есть более эффективные решения. Вот пример того, как это сделать:
import to_import_from
class Instrument(object):
locals().update(dict((k,v) for (k,v) in
to_import_from.__dict__.iteritems() if callable(v)))
def __init__(self):
self.flag = True
def direct_method(self,arg1):
self.external_method(arg1, arg2)
Это импортирует все вызываемые функции, определенные в to_import_from
, как методы класса Instrument
, а также добавит еще несколько методов. Примечание: если вы также хотите скопировать глобальные переменные как переменные экземпляра, вам необходимо уточнить проверку. Также обратите внимание, что он добавляет всех вызываемых объектов, которые он находит в пространстве имен to_import_from, включая импорт из других модулей (то есть из импорта модуля в стиле some_func
импорта стиля)
Однако это не ужасно хороший способ сделать это. Лучше вместо этого настроить генерацию кода так, чтобы создавал класс, и ваш класс унаследовал от него. Это позволяет избежать ненужного копирования методов в пространство имен инструмента и вместо этого использовать обычное наследование. например:
class Instrument(to_import_from.BaseClass):
# Add new methods here.