চক্রীয় আমদানি ছাড়াই পাইথন প্রকারের ইঙ্গিত


123

আমি আমার বিশাল শ্রেণিকে দুটি ভাগে ভাগ করার চেষ্টা করছি; ভাল, মূলত "প্রধান" শ্রেণিতে এবং অতিরিক্ত ফাংশন সহ একটি মিশ্রণ, এরকম:

main.py ফাইল:

import mymixin.py

class Main(object, MyMixin):
    def func1(self, xxx):
        ...

mymixin.py ফাইল:

class MyMixin(object):
    def func2(self: Main, xxx):  # <--- note the type hint
        ...

এখন, এটি কেবলমাত্র সূক্ষ্মভাবে কাজ করে, MyMixin.func2অবশ্যই প্রকারের ইঙ্গিতটি কাজ করতে পারে না। আমি আমদানি করতে পারছি না main.py, কারণ আমি একটি চক্রীয় আমদানি পেয়েছি এবং ইঙ্গিত ছাড়া আমার সম্পাদক (পাইচার্ম) কী তা বলতে পারে না self

আমি পাইথন ৩.৪ ব্যবহার করছি, যদি সেখানে কোনও সমাধান পাওয়া যায় তবে 3.5 এ যেতে প্রস্তুত।

আমি আমার ক্লাসকে দুটি ফাইলে বিভক্ত করতে এবং সমস্ত "সংযোগগুলি" রাখতে পারি এমন কোনও উপায় আছে যাতে আমার আইডিই আমাকে এখনও স্বয়ংক্রিয় সমাপ্তির প্রস্তাব দেয় এবং অন্যান্য ধরণের গুডিগুলি যা প্রকারগুলি জেনে থাকে?


4
আমি মনে করি না সাধারণত আপনার প্রকারটি বর্ণনা করতে হবে self, যেহেতু এটি সর্বদা বর্তমান শ্রেণীর একটি সাবক্লাস হতে চলেছে (এবং যে কোনও ধরণের চেকিং সিস্টেমটি এটি নিজেরাই বুঝতে সক্ষম হবে)। হয় func2কল করার চেষ্টা func1, যা সংজ্ঞায়িত করা হয় না MyMixin? সম্ভবত এটি হওয়া উচিত (হিসাবে একটি হিসাবে abstractmethod, সম্ভবত)?
ব্ল্যাককিংহাট

আরও মনে রাখবেন যে সাধারণত আরও নির্দিষ্ট ক্লাস (যেমন আপনার মিক্সিন) ক্লাস সংজ্ঞায় বেস ক্লাসের বামে যাওয়া উচিত, class Main(MyMixin, SomeBaseClass)যাতে আরও নির্দিষ্ট শ্রেণি থেকে পদ্ধতিগুলি বেস শ্রেণীর উপর থেকে ওভাররাইড করতে পারে
এ্যানট্রপিক

4
আমি নিশ্চিত নই যে এই মন্তব্যগুলি কীভাবে কার্যকর তা যেহেতু তারা জিজ্ঞাসা করা প্রশ্নের তুলনায় স্পর্শকাতর। ভেলিস কোনও কোড পর্যালোচনা চাইছিল না।
জ্যাকব লি

উত্তর:


179

সাধারণভাবে আমদানি চক্রগুলি পরিচালনা করার জন্য বিশাল মার্জিত উপায় নেই, আমি ভয় করি। আপনার পছন্দগুলি হয় চক্রীয় নির্ভরতা অপসারণের জন্য আপনার কোডটিকে নতুন করে ডিজাইন করতে হয়, বা যদি এটি সম্ভব হয় না তবে এই জাতীয় কিছু করুন:

# some_file.py

from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from main import Main

class MyObject(object):
    def func2(self, some_param: 'Main'):
        ...

TYPE_CHECKINGধ্রুব সর্বদা Falseতাই আমদানি মূল্যায়ন করা হবে, কিন্তু mypy (এবং অন্যান্য ধরনের-পরীক্ষণের সরঞ্জাম) যে ব্লক বিষয়বস্তু মূল্যায়ন করবে রানটাইম এ।

আমাদের Mainপ্রকারটি টীকাটি স্ট্রিং হিসাবে তৈরি করতে হবে , কার্যকরভাবে এটি ঘোষণা করে এগিয়ে নেওয়া যেহেতু Mainপ্রতীকটি রানটাইমটিতে পাওয়া যায় না।

যদি আপনি পাইথন ৩.7+ ব্যবহার করেন তবে আমরা কমপক্ষে পিইপি 3 56৩ এর সুবিধা নিয়ে সুস্পষ্ট স্ট্রিং টীকাটি সরবরাহ করতে এড়াতে পারি :

# some_file.py

from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from main import Main

class MyObject(object):
    # Hooray, cleaner annotations!
    def func2(self, some_param: Main):
        ...

from __future__ import annotationsআমদানি করতে হবে সব স্ট্রিং হতে টাইপ নির্দেশ এবং তাদের মূল্যায়ন কর। এটি আমাদের কোডকে এখানে হালকাভাবে আরও অ্যারগোনমিক করতে সহায়তা করতে পারে।

যা কিছু বলেছে, মাইপির সাথে মিক্সিনগুলি ব্যবহার করার জন্য সম্ভবত আপনার কাছে এখন আরও কিছু কাঠামোর প্রয়োজন হবে। মাইপি এমন একটি পদ্ধতির প্রস্তাব দেয় যা মূলত যা decezeবর্ণনা করছে - এমন একটি এবিসি তৈরি করতে যাতে আপনার Mainএবং MyMixinশ্রেণি উভয়ই উত্তরাধিকার সূত্রে প্রাপ্ত হয়। পাইচারমের চেকারকে খুশি করার জন্য আপনার যদি অনুরূপ কিছু করার দরকার পড়ে থাকে তবে আমি অবাক হব না।


4
এর জন্য ধন্যবাদ. আমার বর্তমান অজগর 3.4 নেই typing, তবে পাইচার্ম if False:পাশাপাশি বেশ খুশি হয়েছিল ।
ওয়েলিস

একমাত্র সমস্যা হল এটি একটি জ্যাঙ্গো models.Model যেমন MyObject না চেনে এবং এইভাবে খুঁতগুলোও সম্পর্কে উদাহরণস্বরূপ বাইরে সংজ্ঞায়িত হচ্ছে বৈশিষ্ট্যাবলী__init__
velis

এখানে জন্য সংশ্লিষ্ট বীর্য হয় typing. TYPE_CHECKING : python.org/dev/peps/pep-0484/#runtime-or-type-checking
Conchylicultor

29

কেবল টাইপ চেকিংয়ের জন্য ক্লাস আমদানি করার সময় চক্রীয় আমদানিতে লড়াই করা লোকদের জন্য: আপনি সম্ভবত একটি ফরোয়ার্ড রেফারেন্স (পিইপি 484 - টাইপ ইঙ্গিত) ব্যবহার করতে চাইবেন :

যখন কোনও ধরণের ইঙ্গিতটিতে এমন নাম থাকে যা এখনও সংজ্ঞায়িত হয়নি, তখন সেই সংজ্ঞাটি স্ট্রিং আক্ষরিক হিসাবে প্রকাশ করা হতে পারে, পরে সমাধান হওয়ার জন্য।

এর পরিবর্তে:

class Tree:
    def __init__(self, left: Tree, right: Tree):
        self.left = left
        self.right = right

তুমি কর:

class Tree:
    def __init__(self, left: 'Tree', right: 'Tree'):
        self.left = left
        self.right = right

পাইচার্ম হতে পারে। আপনি কি নতুন সংস্করণ ব্যবহার করছেন? আপনি চেষ্টা করেছেন File -> Invalidate Caches?
টমাসজ বার্টকোয়াইক

ধন্যবাদ দুঃখিত, আমি আমার মন্তব্য মুছে ফেলেছিলাম। এটি উল্লেখ করেছে যে এটি কাজ করে, তবে পাইচার্ম অভিযোগ করে। আমি ভেলিসের প্রস্তাবিত ফলস হ্যাক ব্যবহার করে সমাধান করেছি । ক্যাশে অবৈধ করা এটি সমাধান করেনি। এটি সম্ভবত একটি পাইচর্ম ইস্যু।
জ্যাকব লি

4
@ জ্যাকব্লি আপনি পরিবর্তে এবং if False:এটিও করতে পারেন । from typing import TYPE_CHECKINGif TYPE_CHECKING:
ভাগ্যডায়োন্ড

11

আরও বড় সমস্যাটি হ'ল আপনার প্রকারগুলি শুরু করা বুদ্ধিমান নয়। MyMixinএটি একটি হার্ডকোডযুক্ত ধারণা তৈরি করে যে এটি মিশ্রিত হবে Main, অন্যদিকে এটি যে কোনও সংখ্যক শ্রেণীর সাথে মিশ্রিত হতে পারে, সেই ক্ষেত্রে এটি সম্ভবত ভেঙে যাবে। যদি আপনার মিশ্রিনটি একটি নির্দিষ্ট শ্রেণিতে মিশ্রিত করার জন্য হার্ডকোডযুক্ত থাকে তবে আপনি সেই পদ্ধতিগুলি আলাদা না করে সরাসরি সেই শ্রেণিতে সরাসরি লিখতে পারেন।

বুদ্ধিমান টাইপিংয়ের সাথে এটি সঠিকভাবে করতে, MyMixinএকটি ইন্টারফেসের সাথে কোড করা উচিত , বা পাইথন পার্লেন্সে অ্যাবস্ট্রাক্ট ক্লাস:

import abc


class MixinDependencyInterface(abc.ABC):
    @abc.abstractmethod
    def foo(self):
        pass


class MyMixin:
    def func2(self: MixinDependencyInterface, xxx):
        self.foo()  # ← mixin only depends on the interface


class Main(MixinDependencyInterface, MyMixin):
    def foo(self):
        print('bar')

4
ভাল, আমি বলছি না যে আমার সমাধানটি দুর্দান্ত। কোডটি আরও পরিচালনাযোগ্য করার জন্য এটি করার চেষ্টা করছি just আপনার পরামর্শটি পাস হতে পারে তবে এর অর্থ হ'ল আমার নির্দিষ্ট ক্ষেত্রে পুরো মেইন ক্লাসটি ইন্টারফেসে নিয়ে যাওয়া ।
velis

3

আমার মূল প্রচেষ্টাটিও সমাধানটির খুব কাছে ছিল Turn আমি বর্তমানে এটি ব্যবহার করছি:

# main.py
import mymixin.py

class Main(object, MyMixin):
    def func1(self, xxx):
        ...


# mymixin.py
if False:
    from main import Main

class MyMixin(object):
    def func2(self: 'Main', xxx):  # <--- note the type hint
        ...

if Falseবিবৃতিটির মধ্যে আমদানিটি নোট করুন যা কখনই আমদানি হয় না (তবে আইডিই তা সে সম্পর্কে জানে) এবং ক্লাসটিকে Mainস্ট্রিং হিসাবে ব্যবহার করে কারণ এটি রানটাইমটিতে জানা যায় না।


আমি এটি মৃত কোড সম্পর্কে একটি সতর্কতা হতে পারে আশা করি।
ফিল

@ ফিল: হ্যাঁ, সেই সময় আমি পাইথন ৩.৪ ব্যবহার করছিলাম। এখন আছে typing.TYPE_CHECKING
velis

-4

আমি মনে করি সঠিক উপায়টি হ'ল কোনও ফাইল (যেমন __init__.py) এবং তারপরে from __init__ import *অন্যান্য সমস্ত ফাইলগুলিতে সমস্ত ক্লাস এবং নির্ভরতা আমদানি করা উচিত ।

এই ক্ষেত্রে আপনি হয়

  1. এই ফাইল এবং ক্লাসে একাধিক উল্লেখ এড়ানো এবং
  2. এছাড়াও অন্যান্য ফাইলগুলির প্রতিটিটিতে একটি লাইন যুক্ত করতে হবে এবং
  3. তৃতীয়টি হ'ল পাইচার্মটি আপনি যে ক্লাসগুলি ব্যবহার করতে পারেন সেগুলি সম্পর্কে জেনে।

4
এর অর্থ হল যে আপনি সর্বত্র লোড করছেন, আপনার যদি ভারী ভারী গ্রন্থাগার থাকে তবে এর অর্থ হ'ল প্রতিটি আমদানির জন্য আপনাকে পুরো লাইব্রেরিটি লোড করতে হবে। রেফারেন্স সুপার ধীর কাজ করবে।
ওমর শ্যাচাম

> এর অর্থ হল যে আপনি সর্বত্র লোড করছেন। >>>> আপনার কাছে অনেকগুলি " init .PY" বা অন্যান্য ফাইল রয়েছে এবং এড়ানো সম্ভব নয় import *, এবং এখনও আপনি এই সহজ পদ্ধতির সুবিধা নিতে পারেন
সাওওমির লেনার্ট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.