Импортирование класса из основного скрипта создает дубликат этого класса? [Дубликат]

Я изменил ответ , чтобы вы могли указать, в каком углу вы хотите быть круглым, и какой из них вы хотите быть резким. также работает на pre-lolipop Пример использования

:

только верхний правый и углы botton-right закруглены

 Path path = RoundedRect(0, 0, fwidth , fheight , 5,5,
                     false, true, true, false);
 canvas.drawPath(path,myPaint);

RoundRect:

    public static Path RoundedRect(
            float left, float top, float right, float bottom, float rx, float ry,
               boolean tl, boolean tr, boolean br, boolean bl
    ){
        Path path = new Path();
        if (rx < 0) rx = 0;
        if (ry < 0) ry = 0;
        float width = right - left;
        float height = bottom - top;
        if (rx > width / 2) rx = width / 2;
        if (ry > height / 2) ry = height / 2;
        float widthMinusCorners = (width - (2 * rx));
        float heightMinusCorners = (height - (2 * ry));

        path.moveTo(right, top + ry);
        if (tr)
            path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
        else{
            path.rLineTo(0, -ry);
            path.rLineTo(-rx,0);
        }
        path.rLineTo(-widthMinusCorners, 0);
        if (tl)
            path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
        else{
            path.rLineTo(-rx, 0);
            path.rLineTo(0,ry);
        }
        path.rLineTo(0, heightMinusCorners);

        if (bl)
            path.rQuadTo(0, ry, rx, ry);//bottom-left corner
        else{
            path.rLineTo(0, ry);
            path.rLineTo(rx,0);
        }

        path.rLineTo(widthMinusCorners, 0);
        if (br)
            path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
        else{
            path.rLineTo(rx,0);
            path.rLineTo(0, -ry);
        }

        path.rLineTo(0, -heightMinusCorners);

        path.close();//Given close, last lineto can be removed.

        return path;
    }

1
задан cricket_007 29 July 2016 в 03:25
поделиться

4 ответа

Когда вы выполняете

./t1.py

, вы выполняете файл t1.py, но он не выполняется как модуль t1. Он считается модулем __main__. (Это то, что проверяет строка if __name__ == '__main__'.) Это означает, что когда эта строка:

import t1

в t2.py пытается импортировать t1, Python начинает выполнение файла t1.py снова , чтобы создать модуль t1. Вы получаете две версии класса A, одна из которых - __main__.A, а другая - t1.A. Модификация t1.A ничего не делает для __main__.A, потому что, хотя они получены из одного и того же кода в том же файле, они не являются тем же классом.

2
ответ дан user2357112 18 August 2018 в 11:39
поделиться
  • 1
    Спасибо за ваш ответ. Это именно то, что я хочу. – 김영석 29 July 2016 в 04:27

Это действительно два разных объекта (очень хорошо объясняется в ответе пользователя user2357112 ). Если вы хотите, чтобы t2 использовал один и тот же объект, вам нужно сообщить Python, что вы фактически импортируете тот же модуль, который импортирует t2. Для этого импортируйте __main__:

import __main__

def f():
    __main__.A.flag = True
    print(__main__.A.flag)
0
ответ дан Community 18 August 2018 в 11:39
поделиться

Да, я вижу, как это может быть немного запутанным, но в основном это вопрос пространств имен, а также различие в том, что пространство имен __main__ не считается частью списка импортированных модулей. Это позволяет файлу, являющемуся точкой выполнения (и, следовательно, занимая пространство имен __main__), также импортироваться в качестве модуля. С другой стороны, если один и тот же модуль импортируется более одного раза, интерпретатор просто позволяет всем различным импортам указывать на одно и то же место в памяти

. Из-за этого в коде, который вы показываете выше, вы на самом деле имеют две разные версии A: у вас есть __main__.A, и у вас есть __main__.t2.t1.A. Второй вопрос возникает из-за того, что __main__ импортирует t2, который, в свою очередь, импортирует t1 в качестве модуля.

Когда вы запускаете t2.f(), вы устанавливаете __main__.t2.t1.A.flag = True, а затем печатаете Это. Впоследствии, когда вы вызываете print(A.flag), вы печатаете значение в __main__.A.flag, которое никогда не менялось.

Надеюсь, что это по меньшей мере немного.

Друг Я всегда говорил, что информатика - экспериментальная наука. Давайте запустим отладчик.

Добавляю pdb.set_trace() к исполнению, а t1.py теперь выглядит так:

#!/usr/bin/python
import t2

class A:
        flag = False

if __name__ == "__main__":
    import pdb; pdb.set_trace()
    t2.f()
    print(A.flag)

И это то, что мы получаем:

$ python t1.py
> /Users/martin/git/temp/t1.py(9)<module>()
-> t2.f()
(Pdb) A
<class __main__.A at 0x10ec9ba78>
(Pdb) t2.t1.A
<class t1.A at 0x10ec9ba10>
(Pdb) 

Обратите внимание, что A имеют отдельные ячейки памяти.

-1
ответ дан Dr K 18 August 2018 в 11:39
поделиться
  • 1
    Это не то, как работает круговой импорт. – user2357112 29 July 2016 в 03:09
  • 2
    Циркулярный импорт, не связанный с __main__, не вызывает такого поведения. Если циклический импорт всегда приводил к повторному выполнению реимпортируемых модулей, вы бы получили переполнение стека из-за бесконечного рекурсивного импорта. __main__ имеет решающее значение. – user2357112 29 July 2016 в 03:48
  • 3
    Это верно, но в этом отношении оно относится к __main__ по-разному. Я соответствующим образом отрегулирую свой ответ. – Dr K 29 July 2016 в 04:04

Вы можете найти это сами:

t1.py

#!/usr/bin/python
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
logger.debug('t1 has started')
logger.debug('t2 is being imported')
import t2

logger.debug('A is being "compiled"')
class A:
    flag = False
logger.debug('ID A: %r', id(A))
logger.debug('ID A.flag %r', id(A.flag))

logger.debug('What is __name__? %r', __name__)
if __name__ == "__main__":
    logger.debug('__name__ was "__main__"')
    logger.debug('Calling t2.f()')
    t2.f()
    logger.debug('t2.f() was called')
    logger.debug('ID A.flag: %r', id(A.flag))
    print(A.flag)

t2.py

#!/usr/bin/python
import logging
logger = logging.getLogger(__name__)
logger.debug('t2 is being imported')

logger.debug('t2 is now importing t1')
import t1

def f():
    logger.debug('f is being called')
    t1.A.flag = True
    logger.debug('ID t1: %r', id(t1))
    logger.debug('ID t1.A: %r', id(t1.A))
    logger.debug('ID t1.A.flag: %r', id(t1.A.flag))
    print(t1.A.flag)

Мой выход

Я раскалываю это с комментариями

DEBUG:__main__:t1 has started
DEBUG:__main__:t2 is being imported
DEBUG:t2:t2 is being imported
DEBUG:t2:t2 is now importing t1

Как вы можете видеть, в первый раз (как отмечали другие) t1 на самом деле имеет имя __main__. Он пытается импортировать t2, но сразу t2 пытается импортировать t1.

DEBUG:t1:t1 has started
DEBUG:t1:t2 is being imported

Вы можете видеть, что ни одно из операторов журнала t2 не запускается. Это потому, что Python кэширует импортированные модули, поэтому он сначала смотрит в кеш для t2 и говорит: «Ага, я уже импортировал этого парня, мне просто нужно вернуть его, вот и все!»

DEBUG:t1:A is being "compiled"
DEBUG:t1:ID A: 140377934341704
DEBUG:t1:ID A.flag 4312040768
DEBUG:t1:What is __name__? 't1'

Итак, вы заметите, что теперь он пробился через импорт t1. И t2

DEBUG:t2:t2 is done being imported

Выполнение продолжается в __main__ t1

DEBUG:__main__:A is being "compiled"
DEBUG:__main__:ID A: 140377934344360
DEBUG:__main__:ID A.flag 4312040768

Обратите внимание, что id для этого A и A.flag

DEBUG:__main__:What is __name__? '__main__'
DEBUG:__main__:__name__ was "__main__"
DEBUG:__main__:Calling t2.f()
DEBUG:t2:f is being called
DEBUG:t2:ID t1: 4317998840
DEBUG:t2:ID t1.A: 140377934341704
DEBUG:t2:ID t1.A.flag: 4312040736

Обратите внимание, что эти id s соответствуют t1.A, а не __main__.A s.

True
DEBUG:__main__:t2.f() was called
DEBUG:__main__:ID A.flag: 4312040768
False
0
ответ дан Wayne Werner 18 August 2018 в 11:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: