这可能是python的理想行为,但我仍然感到困惑-
我具有以下文件结构:
public class SegoeUiEditText extends AppCompatEditText {
private final Context context;
@Override
public boolean isSuggestionsEnabled() {
return false;
}
public SegoeUiEditText(Context context) {
super(context);
this.context = context;
init();
}
public SegoeUiEditText(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
public SegoeUiEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
init();
}
private void setFonts(Context context) {
this.setTypeface(Typeface.createFromAsset(context.getAssets(), "Fonts/Helvetica-Normal.ttf"));
}
private void init() {
setTextIsSelectable(false);
this.setCustomSelectionActionModeCallback(new ActionModeCallbackInterceptor());
this.setLongClickable(false);
}
@Override
public int getSelectionStart() {
for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
if (element.getMethodName().equals("canPaste")) {
return -1;
}
}
return super.getSelectionStart();
}
/**
* Prevents the action bar (top horizontal bar with cut, copy, paste, etc.) from appearing
* by intercepting the callback that would cause it to be created, and returning false.
*/
private class ActionModeCallbackInterceptor implements ActionMode.Callback, android.view.ActionMode.Callback {
private final String TAG = SegoeUiEditText.class.getSimpleName();
public boolean onCreateActionMode(ActionMode mode, Menu menu) { return false; }
public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; }
public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return false; }
public void onDestroyActionMode(ActionMode mode) {}
@Override
public boolean onCreateActionMode(android.view.ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onPrepareActionMode(android.view.ActionMode mode, Menu menu) {
menu.clear();
return false;
}
@Override
public boolean onActionItemClicked(android.view.ActionMode mode, MenuItem item) {
return false;
}
@Override
public void onDestroyActionMode(android.view.ActionMode mode) {
}
}
其中repo/
foo/
__init__.py
foo/
bar.py
如下:
__init__.py
当我从from .foo import bar
中输入python解释器时,我可以像这样导入repo/
:
bar
太好了!但是,以下方法不起作用:
>>> from foo import bar
>>> bar
<module 'foo.foo.bar' from '.../repo/foo/foo/bar.py'>
也许我对python的import语句的工作方式不了解,但是我非常希望能够如上所示进行导入。如果这是期望的行为,那么有人知道解决方法吗?也许我可以在>>> import foo.bar as foobar
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'foo.bar'
中进行更改?
出于对命名注意事项的考虑,我还使用以下文件结构对此进行了测试:
__init__.py
...我得到相同的结果
我已经在linux和macOS上的python 3.6.2和3.6.6中对此进行了测试。我还在python 2.7.13中看到了相同的行为(当然,我在较低的repo/
foo/
__init__.py
baz/
bar.py
目录中添加了__init__.py
。
如果我无法进行这种类型的导入工作,foo/
将不得不进行一些重构。帮我防止这种情况!
答案 0 :(得分:2)
要导入的模块的实际名称为foo.foo.bar
。您在from .foo import bar
中的__init__.py
不会改变。
from foo import bar
将为您提供bar
模块对象的foo
属性,而实际上正是您想要的模块,这要感谢__init__.py
中的这一行。不过,import foo.bar
需要一个实际的foo.bar
模块。如果在sys.modules
中找不到该名称的条目,则将引发错误。不要试图用sys.modules
来解决这个问题。导致really confusing double-import bugs。