لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 09/08/21 في كل الموقع
-
لدي بيانات على الشكل التالي: 1 2 0 April 4.0 1 August 8.0 2 December 12.0 3 February 2.0 4 January 1.0 5 July 7.0 6 June 6.0 7 March 3.0 8 May 5.0 9 November 11.0 10 October 10.0 11 September 9.0 أريد ترتيبهم بناء على قيم العمود رقم 2 تصاعديا، كيف يمكنني فعل هذا؟2 نقاط
-
أنشأت بيئة virtualenv، ثم قمت بتثبيت جانغو Django. عندما أقوم بتنشيط virtualenv وتنفيذ الأمر التالي: python management.py syncdb أحصل على هذا الخطأ: django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No module named MySQLdb لقد قمت أيضًا بمحاولة تثبيت حزمة MySQL لـ Python ، لكن دون جدوى، كيف أحل هذه المشكلة؟ أنا أستخدم Python 3.71 و Django 1.9 و MySQL على نظام تشغيل لينكس2 نقاط
-
أريد استبدال المسافات البيضاء بشرطة سفلية _ في نص معين لإنشاء عناوين Slug. لذلك أريد تحويل النص على النحو التالي: "How can this be achieved" => "How_can_this_be_achieved" لكن المشكلة أن النص قد يحتوي على مسافات مختلف مثل \n أو \t أنا أستخدم Python مع جانغو Django. هل يمكن حل ذلك باستخدام regular expressions؟2 نقاط
-
لدي بيانات على شكل dataframe بحيث تحتوى على تواريخ، وكل تاريخ مربوط به حدث أو أكثر أو ليس به أحداث إطلاقا، التواريخ من المفترض أنها لشهر كامل، الا انني عندما أقوم بعمل groupby لجمع عدد الأحداث سوياً في كل تاريخ تابعه لها، يكون عدد التواريخ أقل من 30، وذلك لأن هناك بعض الأيام ليس بها أحداث فيتم إزالتها مباشرة كالتالي: df.groupby(['simpleDate']).size() 09-02-2021 2 09-03-2021 10 09-06-2021 5 09-07-2021 1 لاحظ أن هناك تواريخ في المنتصف تم ازالتها لانها لا تحتوى على أحداث. أريد طباعة تلك التواريخ أيضا بحيث يكون عدد الأحداث بها 0 ولا يتم تجاهلها، كيف يمكنني فعل هذا؟2 نقاط
-
2 نقاط
-
كيف اعمل كلاس لارسال بريد الكتروني php يعني استطيع استخدام هذا الكلاس في كل مكان في مشروعي2 نقاط
-
أقوم بانشاء بيانات تحتوى على بعض المدن والمكاتب وكذلك مبيعات تلك المكاتب في المدن كالتالي: df = pd.DataFrame({'city': ['Cairo', 'Dohha', 'Riyadh', 'Dubai'] * 3, 'office_id': range(1, 7) * 2, 'sales': [np.random.randint(100000, 999999) for _ in range(12)]}) df.groupby(['city', 'office_id']).agg({'sales': 'sum'}) بحيث تظهر على الشكل التالي: city office_id sales Cairo 2 839507 4 373917 6 347225 Dohha 1 798585 3 890850 5 454423 Riyadh 1 819975 3 202969 5 614011 Dubai 2 163942 4 369858 6 959285 أريد حساب النسبة المئوية لمبيعات كل مكتب في كل مدينة علما أن محصلة المبيعات لكل المكاتب في كل مدينة = 100% كيف يمكنني فعل هذا؟2 نقاط
-
( [ ]char) كيف استخدمها؟ وهل ممكن استخدامها لتحويل متغير رقمي الى حرفي؟2 نقاط
-
الإصدار 1.0.0
116573 تنزيل
سطع نجم لغة البرمجة بايثون في الآونة الأخيرة حتى بدأت تزاحم أقوى لغات البرمجة في الصدارة وذاك لمزايا هذه اللغة التي لا تنحصر أولها سهولة كتابة وقراءة شيفراتها حتى أصبحت الخيار الأول بين يدي المؤسسات الأكاديمية والتدريبية لتدريسها للطلاب الجدد الراغبين في الدخول إلى مجال علوم الحاسوب والبرمجة. أضف إلى ذلك أن بايثون لغةً متعدَّدة الأغراض والاستخدامات، لذا فهي دومًا الخيار الأول في شتى مجالات علوم الحاسوب الصاعدة مثل الذكاء الصنعي وتعلم الآلة وعلوم البيانات وغيرها، كما أنَّها مطلوبة بشدة في سوق العمل وتعتمدها كبرى الشركات التقنية. دورة تطوير التطبيقات باستخدام لغة Python احترف تطوير التطبيقات مع أكاديمية حسوب والتحق بسوق العمل فور انتهائك من الدورة اشترك الآن بني هذا العمل على كتاب «How to code in Python» لصاحبته ليزا تاغليفيري (Lisa Tagliaferri) وترجمه إلى العربية محمد بغات وعبد اللطيف ايمش، وحرره جميل بيلوني، ويأتي شارحًا المفاهيم البرمجية الأساسية بلغة بايثون، ونأمل في أكاديمية حسوب أن يكون إضافةً نافعةً للمكتبة العربيَّة وأن يفيد القارئ العربي في أن يكون منطلقًا للدخول إلى عالم البرمجة من أوسع أبوابه. رُبط هذا الكتاب مع توثيق لغة بايثون في موسوعة حسوب لتسهيل عملية الاطلاع على أي جزء من اللغة مباشرة وقراءة التفاصيل باللغة العربية. هذا الكتاب مرخص بموجب رخصة المشاع الإبداعي Creative Commons «نسب المُصنَّف - غير تجاري - الترخيص بالمثل 4.0». يمكنك قراءة فصول الكتاب على شكل مقالات من هذه الصفحة، «المرجع الشامل إلى تعلم لغة بايثون»، أو مباشرةً من الآتي: المقال الأول: دليل تعلم بايثون اعتبارات عملية للاختيار ما بين بايثون 2 و بايثون 3 المقال الثاني: تثبيت بايثون 3 وإعداد بيئتها البرمجية المقال الثالث: كيف تكتب أول برنامج لك المقال الرابع: كيفية استخدام سطر أوامر بايثون التفاعلي المقال الخامس: كيفية كتابة التعليقات المقال السادس: فهم أنواع البيانات المقال السابع: مدخل إلى التعامل مع السلاسل النصية المقال الثامن: كيفية تنسيق النصوص المقال التاسع: مقدمة إلى دوال التعامل مع السلاسل النصية المقال العاشر: آلية فهرسة السلاسل النصية وطريقة تقسيمها المقال الحادي عشر: كيفية التحويل بين أنواع البيانات المقال الثاني عشر: كيفية استخدام المتغيرات المقال الثالث عشر: كيفية استخدام آلية تنسيق السلاسل النصية المقال الرابع عشر: كيفية إجراء العمليات الحسابية المقال الخامس عشر: الدوال الرياضية المضمنة المقال السادس عشر: فهم العمليات المنطقية المقال السابع عشر: مدخل إلى القوائم المقال الثامن عشر: كيفية استخدام توابع القوائم المقال التاسع عشر: فهم كيفية استعمال List Comprehensions المقال العشرون: فهم نوع البيانات Tuples المقال الحادي والعشرين: فهم القواميس المقال الثاني والعشرين: كيفية استيراد الوحدات المقال الثالث والعشرين: كيفية كتابة الوحدات المقال الرابع والعشرين: كيفية كتابة التعليمات الشرطية المقال الخامس والعشرين: كيفية إنشاء حلقات تكرار while المقال السادس والعشرين: كيفية إنشاء حلقات تكرار for المقال السابع والعشرين: كيفية استخدام تعابير break وcontinue وpass عند التعامل مع حلقات التكرار المقال الثامن والعشرين: كيفية تعريف الدوال المقال التاسع والعشرين: كيفية استخدام *args و**kwargs المقال الثلاثين: كيفية إنشاء الأصناف وتعريف الكائنات المقال الحادي والثلاثين: فهم متغيرات الأصناف والنسخ المقال الثاني والثلاثين: وراثة الأصناف المقال الثالث والثلاثين: كيفية تطبيق التعددية الشكلية (Polymorphism) على الأصناف المقال الرابع والثلاثين: كيف تستخدم منقح بايثون المقال الخامس والثلاثين: كيفية تنقيح شيفرات بايثون من سطر الأوامر التفاعلي المقال السادس والثلاثين: كيف تستخدم التسجيل Logging المقال السابع والثلاثين: كيفية ترحيل شيفرة بايثون 2 إلى بايثون 31 نقطة -
لا تخدع نفسك، فتقديرات تسعير البرمجيات بصفتها خدمة ليست بالأمر البسيط. دعني أُجمِل لك الأمر، لقد ارتكبتُ عددًا من الأخطاء فيما يخص التقييم. وبفضل تجربتي (وهي أثمن معلّم في الحياة)، اكتشفتُ كيف أقيّم منتجًا ما، وأُحسّن القيمة الدائمة للعميل، وكيف أضيف مضامين ترتقي بالصفقات، وتؤمّن المدفوعات الرقمية، وتتجنب تخفيض قيمة الموجودات التجارية أكثر. وسأشاركك فيما يلي بعضًا مما تعلمتُ. تعقيد تسعير المنتج إن الحل الذي أشاركك إياه بسيط لدرجة لا تُصدّق، وسأعرضه لك بصيغة استعراض تمهيدي. السؤال: ما أكبر صعوبات التسعير؟ الجواب: تحديد المقياس الصحيح للسعر. السؤال: ما الحل؟ الجواب: ارفع سعرك. لا تقلق، سأكشف لك عن ذلك الحل، لكني سأضع مبدأً أسير عليه قبل ذلك، بقولي إنه لا توجد خطوة سهلة أثناء تسعير المنتجات. تسعير المنتجات تجربة معقدة ومليئة بالعوائق لا يمكنك تحديد سعر منتج ما بوضع بعض الأرقام فحسب، بل عليك أيضًا التفكير في الجانب النفسي لدى المشتري. لماذا يُعَد ذلك مهمًا؟ لأنه بصرف النظر عن المنطق التجاري الذي يعكسه سعرٌ ما، فقد لا يتحسسه المستهلك المحتمَل. ولكن، هناك سبب أكثر أهميةً لأخذ الجانب النفسي للمشتري بالحُسبان، وهو أنه لا يشتري بناءً على السعر وحده، بل عندما يدرك قيمة المنتج أيضًا، وذلك بصورة مستقلة عن سعره. إليك خمس خصائص لنفسية المشتري عليك إدراكها أثناء تسعير المنتج: يحتاج المشتري إلى فهم الكيفية التي ستمكّنه فيها برمجيتك بوصفها خدمةً من جني المال: إن تكلفة المنتج هي فقط إحدى المتغيرات التي يحتاج المشتري إلى موازنتها بإمكانية الكسب التي تقدّمها برمجيتك كونها خدمة. يحتاج المشتري إلى استيعاب الجوانب التي تتفوق فيها خصائص منتجك على تلك الخاصة بمنتج منافسيك: عندما نافستُ شركة أومنتشور -التي تقدّر قيمتها بمليارات الدولارات- بشركتي الناشئة الصغيرة، كنت أعلم أني سأتمكن من تحقيق مبيعات، وذلك لإدراكي أن منتجها كان شديد السوء رغم الاستحواذ الذي كانت تحققه، ويشتكي منه عملائي الذين يطلبون مني الاستشارة، ولكن لم يكن لديهم بديل غيرها لإعداد التقارير الإحصائية. وبفضل هذا الذكاء في مجال السوق، علمتُ أن بوسعي تطوير منتج بخصائص تفوقت على منتج تلك الشركة. لا يحتاج المشتري إلى موازنة بين الأسعار، بل بين الخصائص: لا يشتري المستهلكون حلولًا، بل يشترون خصائص، ولذا ستفشل العديد من مخططات الموازنة السعرية المستخدمة بوصفها وسيلة إقناع سوقية. لكن ما السبب في ذلك؟ لأنها -وفقًا لباحثي جامعة ستانفورد- قد تقدّم نمطًا تفكيريًا يُبعد خيار المستهلك عنك ويجعله يختار منافسيك. وبدلًا من التركيز على السعر، فليكن منصبًّا على ما يريده المستهلك فعلًا، أي على الخصائص، وذلك لأن الخصائص تضيف قيمة، وهذا كل ما تتمحور حوله مسألة التسعير. يجب ألا يختار المشتري، بل أنت من عليك الاختيار له: نعيش وسط ثقافة نعتقد فيها أنّه كلما كثرت الخيارات، كان ذلك أفضل. لكن الحال ليست كذلك فيما يخص تسعير برمجيتك بصفتها خدمة. أترى كل تلك الباقات الفاخرة، والخصائص والخيارات الإضافية على صفحة التسعير الخاصة ببرمجيتك مثل خدمة؟ دعكَ منها. فعندما تكثر الخيارات أمام المستهلك، لا ينتقون أيًا منها في نهاية المطاف. يتأثر المشترون بسياق التسعير، وليس فقط بالتسعير: ثمة الكثير من المناورات التي بوسعك تنفيذها في لعبة التسعير. ففي ذهن المستهلك، لا يمثل السعر سوى واحدة من خصائص عديدة تؤثر في قراره. فجوانبٌ بأهمية القيمة وبهامشية حجم الخط، تؤثّر جميعها في خيار الشراء. ورغم تعقيد عملية التسعير، فكلي ثقة بأن اختراقًا بسيطًا من شأنه إحداث ثورة في منهجك المستخدم في تسعير المنتج. وهناك ما يدعم تأكيدي هذا في كل من علم النفس والتجربة. سأشرح لك ذلك لاحقًا. ما أكبر صعوبات التسعير؟ علينا أولًا فهم الصعوبة الأكبر في مجال تسعير البرمجيات كونها خدمة. إذ أجرت "زورا" -وهي مزوِّد تجارة اشتراك-، دراسةً استقصائيةً لتحديد المشاكل المتكررة في نماذج تسعير الاشتراك، وهي المنهجية الأكثر شيوعًا في مجال البرمجيات كونها خدمة. إليك ما تبيّن لها: أقرَّ أكثر من نصف المُجيبين أن "تحديد مستوى السعر الصحيح" يمثل الصعوبة الأكبر التي يواجهونها؛ أما المشكلة التي تأتي في المرتبة الثانية من حيث الصعوبة، والتي استغرقت أكثر من ربع الرسم البياني الدائري الخاص بهذه الدراسة، فهي مقاييس السعر التي تُعرّف بأنها: خصائص المنتج التي يُبنى عليها السعر، إلى جانب الطريقة التي تشترط الدفع وفقًا لها بوصفك مزوِّدًا لتلك الخدمة مثل نموذج الاشتراك. وبدمج هاتين المشكلتين معًا، يتّضح جليًّا أن نسبة 75% من مشكلة المجيبين في هذه الدراسة متعلقة بكيفية تسعير منتجهم. وتتضمن تلك الكيفية كلًا من الطريقة والمبلغ. فإذا نجحت شركةُ خدمة برمجيات في حل هذه المعضلة، فيمكنها زيادة الربحية والنمو وتقديم قيمة أكبر لعملائها. إن الإيجابيات المحتملة لاستراتيجية تسعير مثالية هائلة، لكن المشكلة تكمن في كيفية الوصول إلى تلك الاستراتيجية. دعني أعطيك الحل البسيط، ثم سأشرح لك السبب الذي يجعله منطقيًا. ما الحل؟ ارفع سعرك كل ما عليك فعله للاقتراب من مستوى السعر الصحيح هو جعل سعرك أعلى مما تظن أنه يجب أن يكون. من الواضح أنه لا يمكنني إعطاؤك صيغة لتحديد نقطة السعر الأصلية الخاصة بك. ما الذي يجعلني عاجزًا عن ذلك؟ هل تتذكر مسألة التعقيد التي تحدثتُ عنها للتقديم لهذه المقالة؟ عليك تحديد تكلفة الإنتاج، وتوقعات الإيرادات، وتكلفة الاستحواذ على عميل، إلخ. ثم عليك تحديد النقطة التي تكسب عندها مالًا كافيًا. يمكنك البدء بتكلفتك المعتادة، ثم تضيف إليها استراتيجية هامش السعر، وبعدها تأخذ الرقم الناتج عن ذلك، وترفعه إلى رقم أعلى، وأعلى من ذلك، ثم أعلى قليلًا، بعدها ترفع السعر أعلى من ذلك أيضًا. كيف يذلل السعر الأعلى صعوبات التسعير الكبرى لنعُد إلى صعوبات التسعير لدى مزوِّد تجارة الاشتراك المسمى "زورا"، ونحدد كيف يمكن لهذه الاستراتيجية التغلّب على الصعوبات: القصور الذاتي عن تغيير تسعيرنا: هذه مشكلة في الواقع؛ فلتتذكر أن القصور الذاتي (أو العطالة، في الفيزياء) في جسم مادي يميل إلى مقاومة أي تغييرات على حالته من السكون إلى الحركة. ولذا عليك استخدام قوة متفجرة لتحقيق ذلك التغيير، مثل تلك التي تُحدثها قنبلة. فإذا كنت صاحب القرار في مؤسستك، فعليك اتخاذ فعل جذري حاسم لتحقق ذلك التغيير. تحديد مقياس السعر الصحيح: لا يوجد مقياس وحيد يحدد استراتيجية التسعير الصحيحة. فهناك حقيقتان اثنتان فقط في هذا الشأن، هما: نموذج الاشتراك وتسعير القيمة، ويُقصَد به تسعير منتج ما وفقًا للقيمة التي يعطيها للمستهلك، ولا شيء غير ذلك. تحديد مستوى السعر الصحيح: هذه مشكلة الارتباك وغياب الوعي البسيطة. يشرح الجزء المتبقي من هذه المقالة السبب الذي يجعل سعرًا أعلى الاستراتيجيةَ الأفضل للتسعير. العوائق المؤسساتية الداخلية: فمَن الذي يرغب في الاعتراض على هوامش الربح والرواتب الأعلى وأسعار الأسهم المتصاعدة؟ العوائق التي تفرضها النُّظم: يبرر السعرُ المرتفع وهوامش الربح العالية، استخدامَ نظام تجارة أفضل. فإذا كان نظامٌ أفضل من سواه فسيدرّ عليك مزيدًا من المال، ولتشتره إذًا. بم سيفكر عملاؤك؟ يقول بول غراهام: عندما يتذمر المشترون ومع ذلك يشترون، تكون قد عثرتَ على سعر السوق. هذا قولٌ مضلِّل، لكنه لا يخلو من حقيقة. إذ يقصد غراهام من ذلك إيصال رسالة مفادها أن عملاءك يحبون منتجك لدرجة تجعلهم يدفعون أيّ سعر للحصول عليه. ولكن الناس بالتأكيد لا يريدون دفع مزيد من المال لك؛ إذ لا نود خسارة أموال إضافية، ولكن عندما يدرك المستهلك قيمة منتجك بالموازنة مع سعره، فلا يفكر في توفير المال. يحيلنا ذلك إلى السبب الأصلي وراء القيمة المطلوبة، فالمستهلكون لا يشترون سلعة بل يشترون قيمة. وها هو لينكولن ميرفي متحفظًا على مقولة بول غراهام، إذ يرى أن سعرك ينبغي أن يقترن بقيمة متصوَّرة عند كل مستوى. تحدث عن القيمة لا عن السعر عندما ترفع السعر، فليس ذلك بالمشكلة العظيمة بالنسبة للمستهلكين، لأن القيمة هي الأهم بالنسبة لهم، وليس السعر. فالسعر نسبي تجاه القيمة، وأعني بذلك أنّ المستهلك يفكّر بالقيمة أولًا، ثم يحدد قيمة المنتج نسبةً إلى سعره. أي إن المستهلكين سيدفعون أي مبلغ عليهم دفعه ما دام أن القيمة المتصوَّرة تفوق السعر. يُطلق لينكولن ميرفي -مؤسس شركة الاستشارات المسماة سيكستين فينتشرز Sixteen Ventures- على ذلك وصف تسعير القيمة، ويعرّفه بقوله: إعادة صياغة سعر بالنسبة لخدمة تتوافق مع القيمة المشتقة من استخدام الخدمات، بدلًا من التكلفة الضمنية لإنشاء وتقديم البرمجيات مثل خدمة وأسعار السوق والهوامش المحددة، وغيرها. كلما ارتفع السعر زادت القيمة المتصورة لاحِظ أنّ القيمة المتصورة تختلف عن القيمة الواقعية. لِنَقُل مثلًا إن برمجيتك بصفتها خدمة تكلف 15 دولارًا في الشهر الواحد، فإذا حصل المستهلك على قيمة تُعادِل 500 دولار في الشهر، فسيدفع ذلك المبلغ 15$ بكل رضا. وحتى لو رفعتَ سعرك إلى 455 دولار شهريًا، فسيبقى ذلك المستهلك يثمّن القيمة التي يحصل عليها، لأنه يكسب قيمةً إضافيةً تبلغ 5 دولارات، وهذا ليس مقياسًا نسبيًا، بل ثابتًا. يعمل تغيير مستوى السعر والقيمة لصالح أفضليتك التسويقية، لأن بوسعك رفع تصوّر المستهلكين للقيمة، وذلك برفع السعر. تُسمّى هذه الظاهرة بـ "القيمة المتصوَّرة". ويعرّفها موقع إنفيستوبيديا investopedia الإلكتروني المالي بأنها الأهمية التي يتمتع بها منتج أو خدمة في ذهن المستهلك. يؤثّر التصور الذي لدى المستهلك، تجاه قيمة سلعة ما أو خدمة مُرضية، في السعر الأساسي الذي هو مستعد لدفعه لقاء الحصول عليها، كي تبقى تلك السلعة أو الخدمة مقدَّمةً في المجال التجاري ذي الصلة. وبالنسبة للجزء الأكبر الحاسم، لا يكون المستهلك غالبًا على دراية بالتكلفة الحقيقة للإنتاج ذي الصلة باستخدام المنتجات التي يميل إلى شرائها. وبدلًا من ذلك، يسيطر على ذلك المستهلك شعور داخلي غير محدد تجاه الأشياء، مثل كم من القيمة تساوي منتجات محددة بالنسبة له موازنةً بمنتجات مماثلة لشركات منافسة. لذلك وفي محاولة من المنتجين للحصول على سعر أعلى لمنتجاتهم، فقد يلجؤون إلى استراتيجيات تسويقية لتحقيق قيمة متصوَّرة بارزة لها. يبسّط الأستاذ في جامعة كاليفورنيا، ليف نيلسون، الموضوع بقوله: يمكن للسعر أن يهيمن على التقييم. فلو نظرتَ إلى علبة عطر مُسعّرة بخمسة دولارات، وإلى أخرى بألف وخمسمئة دولار، فستفترض تلقائيًا وبدون تفكير، أن علبة العطر الأعلى ثمنًا بينهما لها قيمة أكبر، حتى ولو كان العطر في كلتا العبوتين هو ذاته. الحقيقة بالنسبة للمستهلك تأتي مع ما يسمى معايير أمان صناعة بطاقات الدفع PCI Compliance. فإذا تصوَّرَ أنّ منتجك ذو قيمة بالنسبة له، فهذا ما يريده، وستجهد في إقناعه بعكس ذلك. ووفقًا للبحث الذي أجرته مجلة جورنال أوف ريتيلنغ، فلدى المستهلكين أربعة دوافع تؤثر في تصوّرهم: القيمة العاطفية للمنتج. الخاصّية الاجتماعية التي تترافق مع اقتناء المنتج. الجودة/ الأداء المشتقيَن من المنتج. سعر المنتج مقابل قيمته. ولك أن تلاحظ خلوّ الخصائص الثلاثة الأولى من كل ما يتعلق بالسعر الحقيقي، بل تتعلق جميعها بالتصوّر؛ أما الخاصية الرابعة (السعر مقابل القيمة)، فهي الوحيدة التي يولي فيها المستهلك أهمية لموضوع السعر. أي يتعلق الأمر برمّته بتصوّر القيمة لدى المستهلك، وهي حقيقة مقنعة تمامًا في تبرير رفعك للسعر لزيادة ذلك التصوّر. السعر الأعلى يعني قيمة فعلية أعلى أجرى باحثو معهد كاليفورنيا للتقنية Caltech وجامعة ستانفورد Stanford تجربة تذوّق مشروب، للوقوف على ما إذا كان المنتج ذو السعر الأعلى سيزيد استمتاع الخاضع للتجربة به. لقد حصل ذلك فعلًا، إذ قال المشاركون الذين تذوقوا المشروب ذا السعر الأعلى إنه ألذ مذاقًا من المشروب الأدنى سعرًا، وذلك رغم أن المشروبين كانا مشروبًا واحدًا موزعًا في زجاجتين. تنطبق هذه الظاهرة على برمجيتك بوصفها خدمة، فكلما زاد التباهي بمنتج ما، زاد إحساس المستخدم بقيمته، وبالمتعة في استخدامه. وهو تكتيك فعال خصوصًا في مجال خدمة البرمجيات، لأن للبرمجية "عنصرًا كبيرًا غير ملموس" حسب وصف ناغاسيمها كاناجال Nagasimha Kanagal في مجلة جورنال أوف مانجمنت أند ماركتينغ ريسرتش Journal of Management and Marketing Research. يمكنك جعل منتجك أفضل بجعله أعلى سعرًا. فبهذه الطريقة تحدد قيمة المنتج. الخاتمة أُسرُّ لرؤيتي مستهلكًا سعيدًا بدفع ماله، لعلميَ أنه مدرك حتمية حصوله على صفقة جيدة، فرضاه ينعكس رضىً لديّ، والخوف من انزعاج المستهلك مسؤول عن قدر كبير من التردد الذي يسبق رفع السعر. ومثلما شرحتُ في السطور السابقة، لا يؤدي سعرك المرتفع إلى خسارة عملائك. بل بالعكس، يمكن للسعر العالي إسعاد العميل بفضل القيمة العالية التي يحصل عليها، فالمستهلكون الذين يحصلون على قيمة من منتجك -سواء أكانت قيمة حقيقية أو متصوَّرة- هم مستهلكون سعداء؛ وحَسْبُ ذلك سببًا لرفع سعرك. ترجمة -وبتصرّف- للمقال How To Price Your SaaS Product لصاحبه Avinash Mittal. اقرأ أيضًا استراتيجيات التسعير واتجاهاتها الحديثة والمستقبلية وتطوير المنتجات المنتج وتصنيفه ودورة الحياة التي يمر بها مالم يخبرك به علماء النفس عن تسعير المنتجات كيف تختار السعر الملائم للمنتج؟ أهداف تسعير المنتج واستراتيجياته المختلفة مجموعة نصائح تحقق النمو لمشروعك التجاري الصغير عبر الإنترنت النسخة العربية الكاملة لكتاب: مدخل إلى التسويق1 نقطة
-
السلام عليكم عايز اعرف هل Algorithms and data structures مهم لتعيلم data science و ML? بمعنى هل هتفيد في المجالين مع العلم اني يحتاج لغه بايثون هل ممكن تزود من تحسين الأداء او ليس له صله شكرا1 نقطة
-
أنا أستخدم Material-UI مع Next.JS. أرغب في استخدام مكون Link الخاص ب material ui حتى أتمكن من الوصول إلى المتغير وعناصر واجهة برمجة التطبيقات الأخرى ذات الصلة بواجهة material ui. في الوقت نفسه ، أحتاج إلى استخدام مكون NextJS Link للربط بين الصفحات. إنني أتساءل ، كيف يمكنني استخدام الاثنين معًا حتى أتمكن من الحصول على مزايا الربط لمكون NextJS Link جنبًا إلى جنب مع مزايا التصميم لمكون رابط MaterialUI.1 نقطة
-
عندما أقوم بعرض صفحة باستخدام عارض قوالب جانغو Django ، يمكنني تمرير متغير قاموس Dictionary يحتوي على قيم مختلفة لمعالجتها في الصفحة باستخدام الطريقة التالية: {{ myDict }} هل هناك طريقة للوصول إلى نفس المتغير في JavaScript (ربما باستخدام DOM ، لا أعرف كيف يجعل جانغو Django المتغيرات قابلة للوصول)؟ أريد أن أكون قادرًا على البحث عن التفاصيل باستخدام بحث AJAX استنادًا إلى القيم الموجودة في المتغيرات التي تم تمريرها إلى JavaScript من خلال جانغو Django.1 نقطة
-
أحتاج إلى تحويل الملفين light-theme.less و dark-theme.less من ملفات less إلى css. لا أعرف كيفية القيام بذلك في حزمة webpack وتخزينها في المجلد العام من تطبيقي. كانت محاولتي: module.exports = { module: { rules: [ { test: /\-theme.scss$/, use: [ { loader: 'style-loader', }, { loader: 'css-loader', }, { loader: 'less-loader', }, ], }, ], }, } ولكنها لم تنجح1 نقطة
-
السلام عليكم ورحمة الله وبركاته عندما أفوم بتغيير لون ال .header لا يتم التغيير أحتاج الى المساعدة في معرفة سبب المشكلة CSS .header { background-color: tomato; } <body> <!-- header start --> <div class="header"> xxxxxx <div class="container"> <div class="logo"> <img src="../project/images/logo.webp" alt="logo img"> </div> <ul class="navbar"> <li><a href="#">Home</a></li> <li><a href="#">About</a></li> <li><a href="#">Portofolio</a></li> <li><a href="#">services</a></li> <li><a href="#">prices</a></li> <li><a href="#">Team</a></li> <li><a href="#">Blog</a></li> <li><a href="#">Contact</a></li> </ul> <dv class="clear"></dv> </div> <dv class="clear"></dv> </div> <dv class="clear"></dv> <!-- header end --> </body>1 نقطة
-
لدي بيانات تحتوى على التاريخ كالتالي: import pandas as pd data = {'start_date': [pd.Timestamp('2021-01-24 13:03:12.050000'), pd.Timestamp('2021-01-27 11:57:18.240000'), pd.Timestamp('2021-01-23 10:07:47.660000')], 'end_date': [pd.Timestamp('2021-01-26 23:41:21.870000'), pd.Timestamp('2021-01-27 15:38:22.540000'), pd.Timestamp('2021-01-23 18:50:41.420000')]} df = pd.DataFrame(data) قمت بعمل عمود لحساب الفرق بين تاريخين كالتالي: df['diff'] = df['end_date'] - df['start_date'] لكنة يظهر لي خانة تدعى "days" عندما يكون الفرق بين التاريخين أكبر من 24 ساعة: start_date end_ date diff 0 2021-01-24 13:03:12.050 2021-01-26 23:41:21.870 2 days 10:38:09.820000 1 2021-01-27 11:57:18.240 2021-01-27 15:38:22.540 0 days 03:41:04.300000 2 2021-01-23 10:07:47.660 2021-01-23 18:50:41.420 0 days 08:42:53.760000 كيف يمكنني حساب الفرق بين الأيام دون ظهور العمود days، بحيث يكون الفرق فقط في شكل ساعات ودقائق؟1 نقطة
-
لدي مشروع Vanilla JS بسيط ، مرفق مع webpack. هذا هو ملف webpack.dev.js الخاص بي: const path = require('path'); const webpack = require('webpack'); module.exports = { mode: 'development', devtool: 'eval-source-map', output: { path: path.resolve('public'), filename: 'dist/bundle.js', }, module: { rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader', ], }, { test: /\.svg$/, use: 'file-loader', }, ], }, plugins: [ new webpack.EnvironmentPlugin(['CUSTOM_PATH']), ], devServer: { static: './public', }, }; هذا هو ملف .env الخاص بي: PATH=... عند تشغيل المشروع احصل على Uncaught (in promise) ReferenceError: process is not defined1 نقطة
-
لاحظ أنك تستعمل الصيغة scss بدلًا من less في الخاصية test، وسيكون الكود الصحيح، كالتالي: module.exports = { module: { rules: [ { test: /\-theme.less$/i, // لاحظ صيغة الملفات loader: [ // compiles Less to CSS "style-loader", "css-loader", "less-loader", ], }, ], }, };1 نقطة
-
أقوم باستخدام material ui مع nextjs ولدي هذه الصفحة export default function Index() { const [onScreen, theRef] = useOnScreen({ rootMargin: "-300px", ssr: true }); const classes = useStyles(); return ( <Container maxWidth="sm"> <DummyContainer /> <div ref={theRef} style={{ height: "100vh", padding: "20px", backgroundColor: "green", transition: "all .5s ease-in" }} > {onScreen && ( <Box className={classes.rootBox} my={16}> <Typography variant="h2" gutterBottom> Content Lazy using Intersection Observer </Typography> <Copyright /> </Box> )} </div> <Box className={classes.rootBox} my={4}> <Typography variant="h2" gutterBottom> Content no lazy, why this Box loses margin? </Typography> <Typography gutterBottom> If you request this page with JavaScript disabled, you will notice that has been properly rendered in SSR </Typography> </Box> </Container> ); } عند تحديث الصفحة يتشوه ال css الخاص بعناصر ال box فيما أخطأت؟1 نقطة
-
إن عدم عمل material ui مع next js له حلين، إما تضمين خطأ في صفحة document_ أو استخدام reactStrictMode أولا: نضيف document.js_ في مجلد pages إن لم يكن موجود أو نعدل سطر تضمين material import { ServerStyleSheets } from '@material-ui/core/styles'; ^^^^^^^^^^^^^^^^^^^^^^^ ثانياً: في ملف إعادادت next نزيل reactStrictMode الملف : next.config.js module.exports = { // reactStrictMode: true, حذف أو تعليق } مثال ل document.js_ إن لم يكن موجود: import React from 'react'; import Document, { Html, Head, Main, NextScript } from 'next/document'; import { ServerStyleSheets } from '@material-ui/core/styles'; import theme from '../src/theme'; export default class MyDocument extends Document { render() { return ( <Html lang="en"> <Head> {/* PWA primary color */} <meta name="theme-color" content={theme.palette.primary.main} /> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" /> </Head> <body> <Main /> <NextScript /> </body> </Html> ); } } // `getInitialProps` belongs to `_document` (instead of `_app`), // it's compatible with server-side generation (SSG). MyDocument.getInitialProps = async (ctx) => { // Resolution order // // On the server: // 1. app.getInitialProps // 2. page.getInitialProps // 3. document.getInitialProps // 4. app.render // 5. page.render // 6. document.render // // On the server with error: // 1. document.getInitialProps // 2. app.render // 3. page.render // 4. document.render // // On the client // 1. app.getInitialProps // 2. page.getInitialProps // 3. app.render // 4. page.render // Render app and page and get the context of the page with collected side effects. const sheets = new ServerStyleSheets(); const originalRenderPage = ctx.renderPage; ctx.renderPage = () => originalRenderPage({ enhanceApp: (App) => (props) => sheets.collect(<App {...props} />), }); const initialProps = await Document.getInitialProps(ctx); return { ...initialProps, // Styles fragment is rendered after the app and page rendering finish. styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()], }; };1 نقطة
-
أرجو توضيح المشكلة بصورة أكبر من فضلك، وحدد أي خاصية لا تعمل @Mahmoud Nawwar أرجو في المرة القادمة كتابة سؤال واضح مع إرفاق الشيفرة البرمجية التي تعتقد أنها تسبب الخطأ1 نقطة
-
سنتحدث في المقالات الباقية من هذه السلسلة عن متصفحات الويب، فبدونها لم تكن جافاسكربت لتكون أصلًا، وإذا وُجدت لسبب ما فلم يكن أحد ليلتفت إليها. بُنيت تقنية الشبكات لتكون غير مركزية من البداية، سواءً على الصعيد الفني أو بالنسبة للطريقة التي تطورت بها، فقد أضافت العديد من الجهات الموفِّرة للمتصفحات وظائفًا جديدةً لأغراض محددة بعينها أحيانًا، وبدون تفكير أحيانًا أخرى لتعطينا وظائف ومزايا جديدة في صور سيئة، ثم يدور الزمن بهذه وتلك إلى أن يتبناها أحد ما ثم تصير معيارًا قياسيًا في النهاية. ونرى أنّ هذا قد يكون نعمةً ونقمةً في الوقت نفسه، فمن الجيد ألا يكون لديك تحكم مركزي في نظام مثل الإنترنت ويكون تطوره على يد جهات مختلفة تتعاون أحيانًا فيما بينها بصورة طفيفة، وتكاد تناوش بعضها أحيانًا أخرى؛. لكن من الناحية الأخرى، تعني الطريقة العفوية التي تطور بها الإنترنت أنّ النظام الناتج لن يكون هو الآلية التي يتوقعها البعض من حيث الاتساق النظامي الداخلي، فبعض أجزاء هذا النظام مشوشة إلى حد الحيرة. الشبكات والإنترنت وُجِدت شبكات الحواسيب منذ خمسينات القرن الماضي، ذلك أنك إذا وصلت حاسوبين أو أكثر بسلك لنقل البيانات فيما بينها، فستستطيع فعل الأعاجيب بهذه الشبكة الصغيرة، وعليه فهذه الأعاجيب تزداد عجبًا حين نوصل جميع الحواسيب في العالم ببعضها البعض. وقد بدأت التقنية التي تطبق هذه الرؤية في التطوير في الثمانينيات، ثم حصلنا على الشبكة التي تسمى بالإنترنت، وقد كانت كما حلمنا بها بالضبط. يستخدِم الحاسوب هذه الشبكة ليرسل بِتَّات من البيانات إلى حاسوب آخر، ويجب على كلا الحاسوبين معرفة ماذا يفترض لهذه البِتَّات أن تكون وماذا تمثل من أجل تحقيق تواصل فعال، ويتوقف معنى أي تسلسل من البتات على نوع الشيء المراد التعبير عنه وعلى آلية الترميز encoding mechanism المستخدَمة. يصف بروتوكول الشبكة network protocol أسلوبًا من التواصل عبر أي شبكة، فهناك بروتوكولات لإرسال البريد الإلكتروني وجلبه ومشاركة الملفات، وحتى التحكم في الحواسيب التي قد تكون مصابةً ببرمجيات خبيثة، فيُستخدَم بروتوكول نقل النصوص الفائقة HTTP مثلًا -وهو اختصار لـ Hypertext Transfer Protocol- لجلب الموارد المسمّاة وكتل المعلومات مثل صفحات الويب أو الصور، كما يشترط على الجزء الذي سينشئ الطلب البدء بسطر يشبه السطر التالي مسميًا المورد وإصدار البروتوكول الذي يريد استخدامه: GET /index.html HTTP/1.1 هناك قواعد كثيرة تحكم الطريقة التي يمكن للطالب requester فيها إدخال بيانات أو معلومات في الطلب، والطريقة التي يحزِّم الطرف الآخر بها الموارد المطلوبة، وهو مستقبِل الطلب الذي يعيد هذه الموارد إلى طالبها.. تُبنى أغلب البروتوكولات على بروتوكولات أخرى، حيث يتعامل بروتوكول HTTP مع الشبكة كما لو كانت أداة يضع فيها البِتّات ويتوقع منها الوصول إلى الوجهة الصحيحة بالترتيب المتوقع لها، لكن الواقع المشاهَد يقول عكس ذلك كما رأينا في مقال البرمجة غير المتزامنة في جافاسكريبت. ويعالِج بروتوكول التحكم في النقل TCP -اختصارًا لـ Transmission Control Protocol- هذه المشكلة بما أن كل الحواسيب المتصلة بالإنترنت تفهمه، وقد بُنيت أغلب عمليات التواصل في الإنترنت عليه أصلًا. فكرة عمل بروتوكول TCP هي أنّ الحاسوب يجب أن يكون في وضع انتظار أو استماع للحواسيب الأخرى حتى تكلمه أو تراسله، كما يجب أن يكون لكل مستمِع رقمًا يسمى منفَذًا port ويرتبط به من أجل أن تستطيع استماع عمليات تواصل مختلفة في الوقت نفسه على آلة واحدة، كما تحدد أغلب البروتوكولات المنفَذ الذي يجب استخدامه افتراضيًا، فحين نريد إرسال بريد إلكتروني باستخدام بروتوكول SMTP مثلًا، فيجب أن تستمع الآلة التي نرسله من خلالها إلى المنفَذ 25، ثم سينشئ حاسوب آخر حينئذ اتصالًا من خلال التوصيل بالآلة الهدف مستخدمًا رقم المنفَذ الصحيح، فإذا استطاع الوصول إلى الآلة الهدف وكانت تستمع لهذا المنفَذ، فسنقول أنّ الاتصال تحقق بنجاح، كما يُسمى الحاسوب المستمع هنا بالخادم server والحاسوب المتصَل به بالعميل client. يعمل مثل ذلك الاتصال على أساس خط أنابيب ثنائي الاتجاه يمكن للبِتّات أن تتدفق فيه من كلا الاتجاهين، مما يعني استطاعة كلا الحاسوبين إرسال البيانات واستلامها عبره، وبمجرد أن تُنقل البِتّات بنجاح، فسيمكن للآلة التي على الطرف الآخر قراءتها مرةً أخرى، وهذا النموذج مريح جدًا، بل يمكن القول أنّ TCP هو النموذج المجرَّد للشبكة. الشبكة العنكبوتية العالمية The Web تُعَدّ الشبكة العنكبوتية العالمية -أو الويب- مجموعةً من البروتوكولات والصيغ التي تسمح لنا بزيارة صفحات الويب داخل متصفح ما، وتشير كلمة الشبكة العنكبوتية فيها إلى حقيقة إشارة هذه الصفحات إلى بعضها بعضًا وارتباطها ببعضها، وبالتالي تكوّن شبكةً عملاقةً يستطيع المستخدِم التنقل خلالها بحُرية، كما يجدر بنا الإشارة هنا إلى أنّ هذه الشبكة ليست هي كل الإنترنت، فالأخير أوسع وأشمل. لكي تكون جزءًا من هذه الشبكة، لا تحتاج إلا إلى توصيل آلة بالإنترنت وتجعلها تستمع إلى المنفَذ 80 ببروتوكول HTTP كي تستطيع الحواسيب الأخرى طلب مستندات وملفات منها، ويُسمى كل مستند على الشبكة بمحدِّد موقع الموارد الموحَّد Uniform Resource Locator -أو URL اختصارًا-، حيث يكون أشبه بما يلي: http://eloquentjavascript.net/13_browser.html | | | | protocol server path يخبرنا أول جزء أنّ هذا الرابط يستخدم بروتوكول HTTP على خلاف بروتوكول HTTP المشفَّر مثلًا التي سيكون هكذا: https://، ثم يعرِّف الجزءُ الذي يليه الخادمَ الذي نطلب منه المستند، ولدينا في النهاية مسار من سلسلة نصية يعرِّف المستند المحدَّد أو المورد الذي نريد. تحصل الآلات المتصلة بالإنترنت على عنوان IP يكون رقمًا يمكن استخدامه لإرسال رسائل إلى هذه الآلة، حيث يبدو هكذا: 149.210.142.219 أو 2001:4860:4860::8888 غير أن هذه الأرقام المتتالية يصعب حفظها وكتابتها، لهذا تستطيع تسجيل اسم نطاق لأحد تلك العناوين أو بعضها، وقد سجلنا eloquentjavascript.net مثلًا لنشير إلى عنوان IP لآلة نتحكم فيها ونستطيع استخدام اسم النطاق حينئذ لإرسال صفحات الويب لمن يطلبها. إذا كتبتَ محدِّد المواقع ذاك في شريط عنوان المتصفح، فسيحاول المتصفح جلب المستند الذي في ذلك الرابط وعرضه، فيبدأ بالنظر في العنوان الذي يشير إليه eloquentjavascript.net، ثم يستخدِم بروتوكول HTTP ليحقق اتصالًا بالخادم الذي في ذلك العنوان ويطلب المورِد /13_browser.html، وإذا تم ذلك كله فسيرسل الخادم حينئذ مستندًا يعرضه لك المتصفح على الشاشة. HTML تُهيأ صفحات الويب التي تراها أمامك على الشاشة بتنسيق يتكون من تراكيب محددة، واللغة التي نكتب بها تلك التراكيب اسمها HTML أو Hypertext Markup Language وتعني لغة ترميز النصوص الفائقة، ويحتوي المستند العادي المكتوب بهذه اللغة على نصوص ووسوم tags، وتحدد التركيب البنائي لتلك النصوص كما تصف الأنواع المختلفة لها سواءً كانت روابط أو فقرات أو عناوين، وتبدو هذه اللغة هكذا: <!doctype html> <html> <head> <meta charset="utf-8"> <title>My home page</title> </head> <body> <h1>My home page</h1> <p>Hello, I am Marijn and this is my home page.</p> <p>I also wrote a book! Read it <a href="http://eloquentjavascript.net">here</a>.</p> </body> </html> توفِّر الوسوم معلومات عن بنية المستند وتحاط بقوسين محددين هما رمزا "أصغر من" و"أكبر من" في الرياضيات كما ترى في المثال أعلاه؛ أما بقية النص فيكون نصًا عاديًا، كما يبدأ المستند بوسم <!doctype html> الذي يخبر المتصفح أن يفسر الصفحة وفق لغة HTML الحديثة وليس الإصدارات القديمة المختلفة منها والتي تكون عادةً قبل HTML5. تمتلك مستندات HTML في الغالب ترويسةً head ومتن body، كما تحتوي الترويسة على معلومات عن المستند؛ أما المتن فيحتوي على النصوص التي في المستند نفسه، وفي هذه الحالة تقول الترويسة أنّ عنوان هذه المستند هو "My home page" وأنها تستخدِم ترميز UTF-8 الذي هو أسلوب نتبعه لترميز نصوص اليونيكود على أساس بيانات ثنائية. يحتوي متن المستند على ترويسة واحدة، وهي <h1> التي تعني الترويسة الأولى، و<h2> حتى <h6> لتشير إلى ترويسات فرعية، كما يحتوي على فقرتين اثنتين محدَّدتين بوسم <p>. تأتي الوسوم في أشكال كثيرة، فيبدأ العنصر مثل المتن أو الفقرة أو الرابط بوسم افتتاحي مثل <p>وينتهي بوسم غالق مثل </p>، وقد تكون بعض الوسوم الافتتاحية فيها معلومات أكثر مثل وسم <a> في صورة أزواج من name="value"، وتسمى هذه المعلومات بالسمات attributes، وفي حالتنا فإن وجهة الرابط توضَّح بالآتي: href="http://eloquentjavascript.net" وتشير href هنا إلى مرجع لنص فائق hypertext reference. قد لا تغلف بعض الوسوم أيّ شيء ولا تحتاج إلى إغلاقها، ويُعَدّ وسم البيانات الوصفية metadata الذي يأتي بصورة الآتية مثالًأ على ذلك: <meta charset="utf-8"> إذا أردنا كتابة أقواس محددة <> داخل نص مستند لتظهر كما هي من غير تفسيرها على أنها محددات وسوم، فيجب كتابتها بصيغة خاصة بها، بحيث يُكتب القوس الابتدائي < الذي يمثل علامة "أقل من" في الرياضيات على الصورة <، وكذلك القوس الغالق > الذي يمثل علامة أكبر من في الرياضيات على الصورة >. وهكذا، نكتب محرف آمبرساند & ثم اسم المحرف أو رمزه ثم فاصلة منقوطة ;، وتُعرف هذه الصيغة باسم الوحدة entity، حيث تُستبدَل بالمحرف الذي تعبِّر عنه، وذلك مشابه للطريقة التي تُستخدَم بها الشرطة المائلة العكسية في سلاسل جافاسكربت النصية. بما أنّ هذه الآلية تعطي معنى خاصًا لمحارف &، فإنها بذاتها تحتاج إلى تهريب بأن تُكتب & لتظهر بصورتها إذا احتجنا إلى إظهارها في النص، وبالمثل لما بين قيم السمات المغلفة بعلامات تنصيص مزدوجة، إذ يمكن استخدام " لإدخال محرف علامة التنصيص ليظهر بصورته. تُحلَّل HTML بأسلوب يتسامح كثيرًا مع الأخطاء، فإذا كان أحد الوسوم مفقودًا من موضع ما أو نسينا كتابته، فسيكتبه المتصفح ليعالج الخلل، وقد اعتُمِد الأسلوب الذي يحدث به ذلك بحيث تستطيع الاعتماد على جميع المتصفحات الحديثة التي تفعل الشيء نفسه لمعالجة أخطاء الكتابة. انظر المستند التالي الذي سيعامَل على أنه المستند الذي كتبناه في المثال أعلاه رغم أخطاء الصياغة والبناء التي فيه: <!doctype html> <meta charset=utf-8> <title>My home page</title> <h1>My home page</h1> <p>Hello, I am Marijn and this is my home page. <p>I also wrote a book! Read it <a href=http://eloquentjavascript.net>here</a>. عرف المتصفح قد أنّ وسوم <html> و<head> و<body> ليست موجودة، وعرف أنّ الوسمين <meta> و<title> ينتميان إلى الترويسة، والوسم <h1> تعني أنّ متن المستند بدايته من هنا. كما لم يعد هناك حاجة إلى إغلاق الفقرات بصورة صريحة بما أنّ بدء فقرة جديدة أو إنهاء المستند سيغلقها ضمنيًا، ولعلك لاحظت إن كنت منتبهًا إلى أن علامات التنصيص التي حول قيم السمات ليست موجودة أيضًا. سنهمِل في هذه السلسلة وسوم <html> و<head> و<body> من الأمثلة للاختصار ولإبقاء الأمثلة بسيطة، لكن سنغلق الوسوم ونضيف علامات التنصيص حول السمات، كما قد نهمِل تصريح doctype وcharset، لكن لا يعني هذا أننا نشجعك على ذلك، فقد تجد المتصفح يتصرف بغرابة ويفعل أشياءً سخيفةً إذا أهملتها، لذلك نريدك أن تتصرف كما لو كانت البيانات الوصفية الخاصة بهما موجودة في الأمثلة حتى لو لم تكن ظاهرة فعلًا في النص أمامك. HTML وجافاسكربت ما يهمنا في HTML فيما يتعلق بهذه السلسلة هو وسم <script>، إذ يسمح لنا بإدخال شيفرة جافاسكربت داخل المستند. <h1>Testing alert</h1> <script>alert("hello!");</script> ستعمل مثل تلك الشيفرة عندما يرى المتصفح وسم <script> أثناء قراءة HTML، وستُظهر الصفحة نافذة منبثقة حين تُفتح، كما تُشبه دالة alert في المثال أعلاه prompt إلا أنها تخرج نافذة منبثقة تعرض رسالةً ما دون طلب إدخال أي بيانات. يمثِّل المثال السابق برنامجًا صغير الحجم؛ أما إدخال برامج كبيرة مباشرةً في HTML فهو غير عملي، وبدلًا من ذلك يمكن تزويد وسم <script> بسِمة src لجلب ملف سكربت خارجي من رابط URL ما، وهو ملف نصي يحتوي على برنامج جافاسكربت. انظر المثال التالي حيث يحتوي ملف code/hello.js على البرنامج السابق نفسه alert("hello!"). <h1>Testing alert</h1> <script src="code/hello.js"></script> حين تشير صفحة HTML إلى روابط أخرى لتكون أجزاء منها مثل صورة أو ملف سكربت، فستجلبها المتصفحات مباشرةً أثناء تحميل الصفحة لتعرضها لك مع الصفحة نفسها في الأماكن التي حددها ملف HTML. يجب إغلاق وسم <script> دومًا بوسمه الغالق </script> حتى لو كان يشير إلى ملف سكربت لا يحتوي أي شيفرة، فإذا نسيت ذلك، فسستُفسَّر بقية الصفحة على أنها جزء من السكربت. تستطيع تحميل وحدات ES -التي وردت في مقال الوحدات Modules في جافاسكريبت- في المتصفح بتزويد وسم script بسِمة type="Module"، كما يمكن أن تعتمد مثل هذه الوحدات على وحدات أخرى باستخدام روابط متعلقة بها على أساس أسماء وحدات في تصريحات import. كذلك يمكن لبعض السمات أن تحتوي على برنامج جافاسكربت، فالوسم <button> الذي في المثال التالي والذي سيُظهر زرًا به سمة onclick، كما ستعمل قيمة السمة في كل مرة نضغط على الزر فيها. <button onclick="alert('Boom!');">لا تضغط هنا</button> لاحظ أننا اضطررنا لاستخدام علامات تنصيص مفردة للسلسلة النصية التي في سمة onclick لأن العلامات المزدوجة كانت مستخدِمة سلفًا للسمة ككل، لكن كان بإمكاني أن أستخدم ;quot& كذلك. داخل صندوق الاختبارات sandbox لا شك أنّ تشغيل البرامج المحمَّلة من الإنترنت قد يكون خطيرًا، إذ أنك لا تدري مَن وراء أغلب المواقع التي تزورها، وقد يكون فيهم الخبيث واللئيم، كما أنه لا نريد اختراق حواسيبنا بسبب إغفالنا لأمر مثل هذا، لكن الجميل في الموضوع هنا أنك تستطيع تصفح الويب دون الحاجة إلى توكيد الثقة في كل صفحة تزورها، لهذا فإنّ المتصفحات تحدّ كثيرًا من الصلاحيات التي تكون لبرامج جافاسكربت، فلا تستطيع النظر في الملفات التي على حاسوبك أو تعديل أي شيء غير متعلق بالصفحة التي هي فيها. ويسمى هذا العزل لتلك البرامج بصندوق الرمل أو صندوق الاختبار Sandbox، وإن كانت الترجمة الحرفية له هي صندوق الرمل إلا أنّ وظيفته هي عزل البرمجيات التي لا نثق فيها إلى حين البَت في أمرها أو تنتفي الحاجة إليها، وتعمل هذه البرامج كما تشاء داخل هذا الصندوق دون أذى للحاسوب نفسه أو لبياناتك، فلو كان هذا الصندوق قفصًا حديديًا سميك الجدران، فستكون البرامج حينها هي الكائنات التي تعبث فيه كما تشاء دون أن تؤذي من هو خارج القفص، ودون أن تستطيع هي نفسها الخروج. لكن الأمر الصعب عند التعامل مع هذا الصندوق هو السماح لهذه البرامج بفسحة تكفي لتكون مفيدةً مع حجزها عن التسبب في أذى للحاسوب والبيانات التي عليه في الوقت نفسه، لكن احذر أن تشمل هذه الفسحة أمورًا مثل التواصل مع الخوادم الأخرى وقراءة محتويات حافظة النسخ واللصق، فهنا قد يتطور الأمر إلى منحى خطير على الخصوصية. قد يخرج علينا أحد بين الحين والآخر بطريقة جديدة للتحايل على حدود المتصفح والتسبب في اختراق وأذى للمستخدم من تسريب معلومات طفيفة عنه حتى السيطرة التامة على الجهاز المخترَق، كما يستجيب مطورو المتصفحات لهذه التهديدات بإصلاح الثغرات التي تتسبب فيها إلى حين ظهور مشكلة جديدة، لكن مكمن الخطر هنا هو عدم إدراك المطورين للمشكلة إذا لم تُفضَح وتنتشر، فإذا استغلها أحد أو شركة أو منظمة أو جهة حكومية دون الإبلاغ عنها فستكون هنا الخسائر المحتملة أكبر. التوافقية وحروب المتصفحات كان المتصفح المسيطر على الساحة في بدايات الويب يسمى موزايك Mosaic، ثم انتقل السوق إلى متصفح نِت سكيب Netscape الذي ما لبث أن أفرغ الساحة قهرًا لمتصفح إنترنت إكسبلورر Internet Explorer الشهير الخاص بمايكروسوفت. كانت الجهة التي تقف خلف المتصفح في كل مرة تشعر أنّ لها الحق في اختراع المزايا الجديدة التي تشاء للويب، وبما أن أغلب المستخدِمين كانوا يستخدِمون متصفحها، فستضطر المواقع إلى استخدام تلك المزايا مع غض النظر عن باقي المتصفحات، وهذا سبب الكثير من مشاكل التوافقية للمواقع مع المتصفحات المختلفة. نستطيع القول أنّ هذا كان هو العصر المظلم للتوافقية، والذي كان يُعرف بعصر حروب المتصفحات، كما كان المطورون يجدون أنفسهم بين منصتين أو ثلاث لا تتوافق أي منها مع الأخرى بدلًا من ويب واحدة، وزاد الطين بلة امتلاء المتصفحات التي كانت في السوق في بداية الألفية الثالثة -نحو 2003- بالزلات البرمجية Bugs والمشاكل، وكل متصفح له مشاكله، وهكذا كانت حياة المطورين أشبه بالحرب فعليًا. ظهر بعد ذلك متصفح موزيلا فاير فوكس Mozilla Firefox، وهو فرع لا يهدف للربح من نِت سكيب ليبارز إنترنت إكسبلورر في السوق في أواخر عام 2002، وقد سيطر على حصة كبيرة من السوق لعدم اهتمام مايكروسوفت بمتابعة التطوير وزهدها في مجال المتصفحات حينها، ثم خرجت جوجل بمتصفح خاص بها هو جوجل كروم Chrome، وكذلك شركة آبل بمتصفح سفاري Safari الذي اكتسب شهرةً بسبب أنه يأتي مع أجهزتها تلقائيًا، وبالتالي صار لدينا أربعة متصفحات رئيسية على الساحة بدلًا من واحد فقط. اتجهت هذه الهيئات الأربعة نحو وضع معايير موحَّدة وأساليب هندسية أفضل لتصميم هذه المتصفحات، لتعطينا متصفحات لا تعاني كثيرًا من الزلات البرمجية ولا مشاكل التوافقية، وقد رأت مايكروسوفت مؤخرًا أنّ حصتها في هذا السوق قد تهاوت كثيرًا، فتبنّت هذا الرأي في النهاية في متصفح إيدج Edge الخاص بها واستبدلت به متصفحها القديم. يصب كل هذا في مصلحة من يقرِّر تعلم تطوير الويب هذه الأيام، إذ أن الإصدارات الأخيرة من هذه المتصفحات تكاد تتصرف بالأسلوب نفسه تقريبًا وليس لديها الكثير من الزلات البرمجية. ترجمة -بتصرف- للفصل الثالث عشر من كتاب Elequent Javascript لصاحبه Marijn Haverbeke. اقرأ أيضًا المقال السابق: مشروع بناء لغة برمجة خاصة ما هي البرمجة ومتطلبات تعلمها؟ هيكل البرنامج في جافاسكريبت اكتشاف دعم المتصفحات لميزات HTML5 تنسيقات المتصفحات المخصصة ودعمها وأداءها في CSS1 نقطة
-
كيف يمكننى استعراض الملفات بداخل ارشيف zip في نظام لينكس بدون الحاجة لإستخراج الملف؟1 نقطة
-
في لغة PHP يمكنك التصريح عن نوع متحول ما لسهولة التطوير حيث سيستخدم المحرر هذه التصاريح لمساعدتك في التطوير (ينبهك في حال تمرير متحول من نوع بدل آخر) ولكن هذا التنبيه سيقتصر على المحرر فقط، فعند تنفيذ الشيفرة ستعمل بشكل طبيعي، ولكن قد يسبب ذلك مشاكل مثال // تابع لحساب ناتج ما، يتوقع منه إعادة عدد صحيح function calculate(int $a, int $b){ return $a + $b; } $user->balance = calculate(5, 3.5); // $user->balance = 8 ناتج خطأ لتجنب هذه المشاكل فإن المحرر يقترح عليك كتابة declare(strict_types=1) في رأس الملف وذلك سيخبر PHP عند تنفيذ الشيفرة أن يلتزم بتصاريح الأنواع التي حددتها ويرمي خطأ في حال كانت الأنواع غير متطابقة ذلك سيجنبك الخطأ السابق فعند تنفيذ السطر التالي لن يتم حساب نتيجة خطأ دون أن تشعر ولكن سيتوقف التنفيذ ويظهر خطأ $user->balance = calculate(5, 3.5); // Fatal error: Uncaught TypeError1 نقطة
-
1 نقطة
-
يجب أولاً أن تعلم بوجود ما يسمى بال Scalar types والذي يعني نوع بيانات يحمل قيمة واحدة مثل Integer, string, float ,boolean عكسه لدينا الcompound types مما يعني نوع بيانات يحمل أكثر من قيمة مثل array, map , حسناً , نرجع لسؤالك ماهو الstrict types? كما تعلم على الرغم من توافر إمكانية تعريفك للمتغير كنوع معين مثل function test(int $a, float $b) : int { return $a + $b; } test("sharaf",4) هنا قمنا بتعريف الparameters التي تمر بالدالة test أنهم من النوع int & float على الرغم من ذلك قمنا بتمرير parameters من النوع string, int ومع ذلك سيعمل البرنامج دون أن يلقي خطأ, فائدة الstrict decleration أن يقوم بإلقاء خطأ عند محاولة تمرير بيانات من نوع غير المطلوب, وذلك لضمان أن يقوم المبرمج بكتابة برنامج منظم بشكل أكبر وأسهل للقراءة وأقل عرضة للbugs , فمثلاً الكود بالأعلى إن قمنا بتشغيله عند تفعيل الوضع الصارم(strict declaration) سيقوم بإلقاء خطأ Fatal error: Uncaught TypeError1 نقطة
-
أريد أن يتمكن المستخدمون على الموقع من تنزيل الملفات التي تكون مساراتها محجوبة حتى لا يمكن تنزيلها مباشرة. على سبيل المثال، أود أن يكون عنوان URL مثل هذا: http://example.com/download/?f=somefile.txt وعلى الخادم، أعلم أن جميع الملفات القابلة للتنزيل موجودة في المجلد /home/user/files/ بشكل إفتراضي. هل هناك طريقة لجعل جانغو Django يقدم هذا الملف للتنزيل بدلاً من محاولة العثور على عنوان URL ووضعه في view مخصص؟1 نقطة
-
أيضاً للحصول على حل بسيط للغاية لاستخدمه في النماذج الأولية يمكنك فقط استخدام طريقة عرض django المدمجة. هذا الحل ممتاز للنماذج الأولية أو العمل لمرة واحدة: from django.views.static import serve file = '/some/path/to/local/file.txt' return serve(request, os.path.basename(file), os.path.dirname(file)) لكن كما ذكرت يصلح للنماذج الأولية وليس للاستخدام العملي.1 نقطة
-
ما الفرق بين الlocalStorage vs sessionStorage1 نقطة
-
يمكنك استخدام الكود التالي from wsgiref.util import FileWrapper from django.http import HttpResponse filename = "/home/stackoverflow-addict/private-folder(not-porn)/image.jpg" wrapper = FileWrapper(file(filename)) response = HttpResponse(wrapper, content_type='text/plain') response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(filename) response['Content-Length'] = os.path.getsize(filename) return response يمكنك من خلال الكود تخزين الملفات في مسار خاص أنت تحدده وعرضها عبر django لبعض المستخدمين أو في أوقات معينة1 نقطة
-
بما أنك تستخدم Expo في مشروعك يمكنك الاستفادة من الحزمة expo-asset لجلب مسار الملف المطلق كالتالي // في الأعلى import { Asset } from 'expo-asset'; // لتنفيذ أمر فتح الملف OpenAnything.Pdf(Asset.fromModule(require('../PDF/quran.pdf')).uri)1 نقطة
-
1 نقطة
-
حاول اعادة تشغيل مخدم التطبيق ومسح التخزين المؤقت باستخدام الأمر npm start -- --reset-cache1 نقطة
-
يمكنك إستخدام الوحدة X-Sendfile: حيث ينشئ django المسار إلى الملف، ولكن يتم معالجة تقديم الملف الفعلي بواسطة Apache / Lighttpd. بمجرد قيامك بإعداد mod_xsendfile، فإن إستخدامه مع العرض الخاص بك يستغرق بضعة أسطر فقط: from django.utils.encoding import smart_str res = HttpResponse(content_type='application/force-download') res['Content-Disposition'] = f"attachment; filename={smart_str(file_name)}" res['X-Sendfile'] = smart_str("path/to/file") return res بالطبع، لن يحدث هذا الأمر إلا إذا كنت تتحكم في الخادم الخاص بك (أي أن لديك القدرة على تنفيذ أوامر على الخادم لإعداد mod_xsendfile)، أو إذا كانت شركة الاستضافة الخاصة بك قد قامت بإعداد ملف mod_xsend بالفعل. ملاحظة: هذه الطريقة لا تعمل إلا مع الملفات التي لديها أسماء من رموز ASCII فقط، وأي ملفات تحمل أسماء برموز مختلفة (حروف عربية، صينية، رموز إموجي .. إلخ) لن تعمل وستسبب خطأ لأن الوجدة X-Sendfile لا يمكنها التعامل مع رموز غير رموز ASCII. ملاحظة: إذا كنت تستعمل Django بإصدار أقدم من 1.7 فيجب أن تستخدم mimetype كما في المثال التالي، حيث تم استبدال mimetype بـ content_type في الإصدار 1.7 response = HttpResponse(mimetype='application/force-download') # < 1.71 نقطة
-
كما أشار سامح. أويمكنك أيضاً تنفيذ الأمرين التاليين لحل المشكلة: sudo apt-get install libpq-dev python-dev # ثم pip install psycopg2 # pip3 install psycopg2 $ لبايثون 3 أيضاً قد يظهر الخطأ "No module named psycopg2.extensions" عندما لايكون هناك مترجم compiler مثبت، ونحن تحتاج إلى واحد لبناء حزمة psycopg2 لذا يكون الحل: # تثبيت الاعتماديات sudo apt-get build-dep python-psycopg2 sudo apt install python3-psycopg2 # Python 3 #virtualenv ثم ضمن ال pip install psycopg2-binary1 نقطة
-
إذا كنت بحاجة إلى استخدام شيء مشابه لسمة "tag" قالب عنوان url ضمن الكود الخاصة بك، فإن Django يوفر الدالة reverse: reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None)¶ يمكن أن يكون viewname اسم نمط URL أو كائن عرض قابل للاستدعاء. على سبيل المثال ، بالنظر إلى عنوان url التالي: from news import views path('archive/', views.archive, name='news-archive') يمكنك استخدام أي مما يلي لعكس عنوان URL: # URL باستخدام اسم عنوان reverse('news-archive') # تمرير كائن قابل للاستدعاء #بهذه الطريقة namespaced هذا غير محبذ لأنه لا يمكنك عكس طرق عرض from news import views reverse(views.archive) إذا كان عنوان URL يقبل الوسطاء، فيمكنك تمريرها في args. على سبيل المثال: from django.urls import reverse def myview(request): return HttpResponseRedirect(reverse('arch-summary', args=[1945])) يمكنك أيضاً تمرير kwargs بدلاً من args. على سبيل المثال: reverse('admin:app_list', kwargs={'app_label': 'auth'}) '/admin/auth/' لا يمكن تمرير args و kwargs إلى reve5rse في نفس الوقت. إذا تعذر إجراء أي تطابق ، فإن reverse يرمي استثناء NoReverseMatch. يمكن لوظيفة reverse عكس مجموعة كبيرة ومتنوعة من أنماط التعابير المنتظمة (regex) لعناوين URL ، ولكن ليس كل واحد ممكن.إن القيد الرئيسي في الوقت الحالي هو أن النمط لا يمكن أن يحتوي على خيارات بديلة عن طريق استخدام ("|"). إذاً يمكنك استخدام هذه الأنماط للمطابقة مع عناوين URL الواردة وإرسالها إلى طرق العرض، ولكن لا يمكنك عكس هذه الأنماط. تسمح لك الوسيطة current_app بتقديم تلميح "hint" إلى ال reslover يشير إلى التطبيق الذي تنتمي إليه طريقة العرض المنفذة حالياً. يتم استخدام وسيطة current_app كتلميح hint لتحليل فضاءات أسماء namespaces التطبيقات في عناوين URL، وفقاً ل namespaced URL resolution strategy. وسيطة urlconf هي وحدة URLconf التي تحتوي على أنماط عنوان URL المراد استخدامها للعكس.1 نقطة
-
يبدو أنك لم تقم بتثبيت قواعد بيانات postgres على الخادم، لذلك يظهر لك خطأ يخبرك أنك بحاجة لتثبيت postgresql-server، ويمكنك حل هذه المشكلة عبر الأمر التالي: sudo apt-get install -y postgresql python-psycopg2 libpq-dev python-dev postgresql-contrib سيقوم هذا الأمر بتثبيت كل الحزم المطلوبة لكي تعمل قواعد بيانات postgres، وفي حالة اكن لديك أكثر من نسخة بايثون مثبته على الخادم، فسيكون أمر التثبيت لبايثون 3 كالتالي: sudo apt-get install postgresql python3-psycopg2 libpq-dev postgresql-contrib بعد ذلك تستطيع أن تقوم بتثبيت حزمة psycopg2 عبر الأمر التالي: pip3 install psycopg21 نقطة
-
طريقة أخرى إضافةً لما قاله سامح وذلك من خلال Library. كما يلي: # coding=utf-8 from django.template.base import Library register = Library() @register.filter def get_item(dictionary, key): return dictionary.get(key) واستخدامه كالتالي: {{ mydict|get_item:item.NAME }} وإذا1 نقطة
-
يمكنك حل المشكلة من خلال عمل custom template filter، كالتالي: from django.template.defaulttags import register @register.filter def lookup(dict, k): return dict.get(k) أستخدم .get بحيث إذا لم يكن المفتاح موجود في القاموس، فإنه يُرجع None بدلًا من أن يظهر خطأ KeyError بعد ذلك. ويمكنك أن تستخدم الفتلر السابق، على النحو التالي: {% for item in list %} {{ user|lookup:item.NAME }} {% endfor %} وفي حالة كنت تستعمل قوالب Jinja2، فهي تدعم جلب القيم من خلال متغيرات بشكل إفتراضي على النحو التالي: {{ user[item] }} أيضًا إن كنت تقوم بالمرور على القيم من القاموس، فتستطيع أحضار كلاً من المفتاح والقيمة من القاموس في الحلقة، بالشكل التالي: {% for key, value in user.items %} {{ value }} {% endfor %}1 نقطة
-
الكلام التالي ينطبق على عدد الوحدات في بقية أنواع الطبقات أيضاً مثل Dense وغيرها في كيراس وتنسرفلو.. num_units هو عدد يشير إلى ال "Learning capacity" أي قدرة الشبكة على التعلم وهي تعكس عدد ال "learned parameters" ضمن الطبقة أي عدد المعلمات التي سيتم تدريبها لمعالجة بياناتك. إن num_units يندرج تحت مفهوم ال Hyperparameters أي المعاملات العليا للنموذج، أي يجب أن تقوم بضبطها من خلال التجريب، أي ليس هناك قاعدة ثابتة لاختيار قيمتها لكن هناك نقاط يجب وضعها بعين الاعتبار عند تحديد قيمتها وهي: زيادة عددها يعطي الشبكة قدرة أكبر على التعلم من نماذج بيانات أكبر و أكثر تعقيداً (تعطي النموذج قدرة أكبر على التعلم من البيانات-يمكنك تخيل الأمر على أنه حجم ذاكرتها فكلما زاد حجمها زادت قدرتها على التعلم-). لكن زيادة عددها قد يجعل النموذج يتجه إلى حالة ال Oveffitting لذا يجب أن تكون حذراً وأن لتجعل حجمها يتناسب مع حجم المشكلة (عدد ال features للعينات وعدد العينات أي حجم الداتاسيت بشكل عام ومدى تعقيدها). تقليل عددها يجعل الشبكة أضعف وأقل قدرة على التعلم من البيانات. وبالتالي قد يتجه النموذج إلى حالة Underfitting. لذا يجب الموازنة بين الأمرين السابقين أي عملية Trade-off بينهما. أما بالنسبة للعدد 128 فهذا ليس رقماً ثابتاً كما أوضحت لك هو Hyperparameter لكن في كثير من الأحيان يكون ملائم. كما تجدر الإشارة إلى أن عدد ال num_units يفضل دوماً أن يتم أخذه من العلاقة 2 أس n أي: 16- 32-64-128-256-512.... لأن هذه الأرقام تسرع عمليات الحساب لأن المعالج يفضلها.1 نقطة
-
يمكننا القيام بذلك من خلال التعليمة التالية: %tensorboard --logdir logs/train لكن يجب أولاً أن نقوم بتحميل الإضافة: %load_ext tensorboard.notebook أو في حال ظهر لديك الخطأ التالي: RuntimeError: Use '%load_ext tensorboard' instead of '%load_ext tensorboard.notebook'. قم باستخدام: %load_ext tensorboard.notebook مثال: %load_ext tensorboard.notebook import tensorflow as tf import numpy as np logdir = 'logs/' writer = tf.summary.create_file_writer(logdir) tf.summary.trace_on(graph=True, profiler=True) @tf.function def forward_and_backward(x, y, w, b, lr=tf.constant(0.01)): with tf.name_scope('logits'): logits = tf.matmul(x, w) + b with tf.name_scope('loss'): loss_fn = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=y, logits=logits) reduced = tf.reduce_sum(loss_fn) with tf.name_scope('optimizer'): grads = tf.gradients(reduced, [w, b]) _ = [x.assign(x - g*lr) for g, x in zip(grads, [w, b])] return reduced # الدخل x = tf.convert_to_tensor(np.ones([1, 2]), dtype=tf.float32) y = tf.convert_to_tensor(np.array([1])) # params w = tf.Variable(tf.random.normal([2, 2]), dtype=tf.float32) b = tf.Variable(tf.zeros([1, 2]), dtype=tf.float32) loss_val = forward_and_backward(x, y, w, b) with writer.as_default(): tf.summary.trace_export( name='NN', step=0, profiler_outdir=logdir) %tensorboard --logdir logs/ الخرج:1 نقطة
-
نعم يمكنك القيام بذلك، كالتالي: # سأقوم بإنشاء نموذج فارغ from keras.models import Sequential model = Sequential() # ثم قم بإنشاء ملف with open(filename + 'report.txt','w') as f: #ليكون قابلاً للاستدعاء lambda قم بتمرير مقبض الملف لل model.summary(print_f=lambda x: f.write(x + '\n')) # وسيكون خرج الملف كالتالي _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= Total params: 0 Trainable params: 0 Non-trainable params: 0 _________________________________________________________________ وإذا أردت كتابته في سجل يمكنك استخدام getLogger من logging: import logging logger = logging.getLogger(__name__) model.summary(print_fn=logger.info)1 نقطة
-
حسناً.. افترض أنك ترغب في تشغيل operator معين في كل مرة يتم فيها تقييم متغير معين. على سبيل المثال ، لنفترض أنك ترغب في إضافة واحد إلى c في كل مرة يتم فيها تقييم المتغير k. قد يبدو لك أن هذا الكود سيعمل: c = tf.Variable(0.0) cp = tf.assign_add(c, 1) with tf.control_dependencies([cp]): k = c init = tf.initialize_all_variables() with tf.Session() as session: init.run() for i in xrange(4): print(k.eval()) #0, 0, 0, 0 # لكن كما تلاحظ لم ينجح الأمر وذلك لأننا بحاجة إلى إضافة عقدة جديدة إلى الرسم البياني داخل كتلة control_dependencies. لذلك في مثل هكذا حالة يمكننا أن نستخدم tf.identity حيث يضيف عقدة وهمية: c = tf.Variable(0.0) cp = tf.assign_add(c, 1) with tf.control_dependencies([cp]): k = tf.identity(c) init = tf.initialize_all_variables() with tf.Session() as session: init.run() for i in xrange(4): print(k.eval()) # 1, 2, 3, 4 وبشكل عام هو مفيد أيضاً عندما تريد نقل tensor بين الأجهزة (مثلاً ، من ال GPU إلى ال CPU). حيث يضيف op عقد الإرسال / الاستلام إلى الغراف ، مما يؤدي إلى إنشاء نسخة عندما تختلف أجهزة الإدخال والإخراج. إن السلوك الافتراضي هو أن تتم إضافة عقد الإرسال / الاستلام ضمنياً عندما تحدث العملية على جهاز مختلف ولكن يمكنك تخيل بعض المواقف (خاصة في الإعدادات multi-threaded/distributed ) عندما يكون من المفيد جلب قيمة المتغير عدة مرات خلال عملية تنفيذ واحدة للجلسة. يسمح tf.identity بمزيد من التحكم فيما يتعلق بوقت قراءة القيمة من الجهاز المصدر.1 نقطة
-
نعم يمكنك استخدام reset_default_graph من ops كالتالي: from tensorflow.python.framework import ops ops.reset_default_graph() sess = tf.InteractiveSession()1 نقطة
-
كما نعلم فإن الأوزان بتم تمثيلها ك tf.Variable في تنسرفلو وهذا ال Variable يمكنك الحصول على قيمته من خلال sess.run(Variable)، الآن إذا أردت الحصول عليه فيمكنك الحصول على قائمة بالمتغيرات Variables القابلة للتدريب (من ضمنها ستكون الأوزان) في الغراف الحالي عن طريق استدعاء tf.trainable_variables. ثم يمكنك الحصول على المتغير الذي تريده من خلال تحديد الخاصية Variable.name. انظر للمثال التالي: #"conv2d/kernel:0" بفرض اسم المتغير الذي نريده هو var = [variable for variable in tf.trainable_variables() if variable.name == "conv2d/kernel:0"][0]1 نقطة
-
الاختلاف الوحيد بينهم هو أن الجلسة التفاعلية "InteractiveSession" تقوم بتثبيت نفسها كجلسة افتراضية عند بناء الغراف (أي إذا لم تعرف أي جلسة بشكل صريح سيتم استخدامها كجلسة افتراضية). انظر مثلاً عندما نقوم بتعريف جلسة عادية لمقطع برمجي في تنسرفلو نقوم بالتالي: import tensorflow.compat.v1 as tf tf.disable_v2_behavior() with tf.Session() as sess: a = tf.constant(4.0) b = tf.constant(2.0) c = a * b print(sess.run(c)) أما باستخدام InteractiveSession: sess = tf.InteractiveSession() a = tf.constant(4.0) b = tf.constant(2.0) c = a * b #sess.run مباشرةً دون الحاجة لتمريرها ل c.eval() لاحظ أننا نستطيع تنفيذ print(c.eval()) sess.close() #8.01 نقطة
-
الفكرة الأساسية هي: استخدام خاصية locale في MaterialApp: إذا كانت `locale` خالية ، فسيتم استخدام القيمة المحلية للنظام. نقوم بتحويل الـ root widget إلى Stateful سيؤدي ذلك إلى إعادة البناء بناءً على المكان والاتجاه اللذين نحددهما. نستخدم Scope Model لحفظ اللغة المستخدمه في التطبيق، ونقوم بتغيرها عندما يتطلب الأمر. فلاتر لا يدعم سوى اللغة الإنجليزية بشكل إفتراضي، لذلك سنحتاج إلى إستخدام حزمة مثل flutter_localizations لإضافة الدعم للغات أخرى في MaterialApp بالإضافة إلى حزمة intl لإضافة ترجمات إلى النصوص. dependencies: flutter: sdk: flutter flutter_localizations: sdk: flutter intl: intl_translation: cupertino_icons: ^0.1.2 scoped_model: "^0.2.0" dev_dependencies: flutter_test: sdk: flutter نقوم بإحاطة التطبيق بـ scope model لحفظ / تغيير اللغة الحالية، وفصل الواجهة عن الكود المنطقي، ليسهل التعديل وصيانة التطبيق فيما بعد. ونقوم بعمل دالة changeDirection لتغير اللغة وإتجاه النص import 'package:flutter/material.dart'; import 'package:scoped_example/my_app.dart'; import 'package:scoped_model/scoped_model.dart'; class ScopeModelWrapper extends StatelessWidget { @override Widget build(BuildContext context) { return ScopedModel<AppModel>(model: AppModel(), child: MyApp()); } } class AppModel extends Model { Locale _appLocale = Locale('ar'); Locale get appLocal => _appLocale ?? Locale("ar"); void changeDirection() { if (_appLocale == Locale("ar")) { _appLocale = Locale("en"); } else { _appLocale = Locale("ar"); } notifyListeners(); } } نقوم بإضافة الخاصية locale إلى MaterialApp في النهاية يمكن أن تضيف الدالة model.changeDirection(); إلى الخاصية onPressed ليتم تغير اللغة من الإنجليزية إلى العربية والعكس. يمكنك أيضًا أن تقوم بتعديل الأكواد السابقة لتقبل الدالة changeDirection مدخل باسم اللغة "ar" أو "en" أو "fr" .. إلخ ويمكنك الإطلاع على كود بسيط ومفتوح المصدر لتغير اللغة في صفحة تسجيل دخول من هذا المستودع.1 نقطة
-
يُعتبر مبدأ المسؤوليّة الواحدة Single Responsibility Principle (أو اختصارًا SRP) المبدأ الأوّل من مبادئ التصميم SOLID، وهو مفيد بصورة خاصّة في التصميم كائنيّ التوجّه object-oriented design. يعتمد هذا المبدأ على تجزئة مكوّنات النظام البرمجي بحيث يكون لكلّ جزء منه مهمّة (مسؤوليّة) واحدة ووحيدة. ينص هذا المبدأ على ما يلي: لا يظهر من النص السابق أي إشارة مباشرة إلى المسؤوليّة الواحدة. لتوضيح الربط بين المسؤولية الواحدة وبين نص المبدأ السابق، لننظر إلى المثال التالي الذي يحوي صنفًا مكتوبًا بلغة ++C ويُستخدم للاتصال بخادوم قواعد بيانات MySQL. اسم هذا الصنف MySQL أيضًا، ويمتلك واجهة لتأسيس الاتصال مع خادوم MySQL وإغلاقه، وإرسال استعلامات SQL إلى الخادوم واستقبال ومعالجة النتائج: class MySQL { public: bool connect(); void disconnect(); bool executeQuery(std::string queryString); MySQLResult* getQueryResult(); }; من الواضح أنّ لهذا الصنف مهمّتان أساسيّتان، الأولى هي إدارة عملية الاتصال مع خادوم MySQL (فتح وإغلاق الاتصال) والثانية هي التواصل مع الخادوم في إجراء الاستعلامات واستقبال النتائج (تنفيذ استعلامات SQL). لو افترضنا الآن حدوث السيناريو التالي: أصبح خادوم MySQL يقبل الاتصالات المشفّرة فقط. حدثت بعض التغييرات ضمن الخادوم بحيث أنّه بدأ بالاستجابة بشكل مختلف لبعض الاستعلامات. سيؤدي ذلك بالطبع إلى حدوث تغييرين ضمن صنف MySQL السابق، أو بمعنى آخر، سيكون هناك سببان لتغيير الصنف MySQL. ويُعدّ هذا خرقًا لمبدأ المسؤولية الواحدة كما هو واضح. يُعتبر وضع أكثر من مهمّة قابلة للتغيير (من أجل سبب ما) لأحد الأصناف خطأً تصميميًّا. قد لا تبدو تلك مشكلةً في الوقت الحالي، ولكن أيّ نظام برمجي يتغيّر ويتطوّر. فما يبدو حلًّا مقبولًا في الوقت الحاضر، قد يُفضي إلى نتائج سيّئة في المستقبل. يمكن استخدام الحل التالي لمشكلتنا السابقة: class MySQLConnection { public: bool open(); /* former connect() */ void close(); /* former disconnect() */ }; class MySQLQuery { MySQLConnection* session; public: bool execute(std::string queryString); MySQLResult* getResult(); }; يبدو مبدأ المسؤوليّة الواحدة بسيطًا، ولكنّه في الحقيقة صعب التطبيق. والسبب في ذلك، هو أنّ وضع المسؤوليّات المتعدّدة لصنف ما معًا، هو أمر بديهي ومألوف بالنسبة إلينا، أمّا عملية الفصل والتجزئة إلى أصناف أصغر لكلٍّ منها مسؤوليّة واحدة، فقد لا تبدو جذّابةً أوّل الأمر. بالنسبة لي، عندما عدت وراجعت بعض تصميمات الأصناف القديمة لديّ، قلّما وجدت صنفًا من الممكن جعله يراعي هذا المبدأ. ولكن عندما أمعنت النظر والتفكير وجدت أنّ الفصل في المهام سيقلّل من تعقيد التصميم، وسيجعل الشيفرة أيسر للقراءة والفهم. بالمقابل، فإنّ تطبيق هذا المبدأ بشكل صارم، ليس فكرةً جيّدة. فعلى المرء أن يكون حكيمًا في تحديد متى يمكن تطبيق هذا المبدأ، وخصوصًا عندما يجد أنّ الملف الخاص بأحد أصنافه بات يحتوي على أكثر من 500 سطر من الشيفرة البرمجيّة! ترجمة -وبتصرّف- للمقال Single Responsibility Principle لصاحبه Radek Pazder.1 نقطة
-
يُعتبر مبدأ الفتح والإغلاق Open/Closed Principle أو اختصارًا OCP، من المبادئ التي تساعد مطوّري البرمجيّات على تحقيق تصاميم برمجيّة عالية الجودة. على أيّة حال، قد يكون من الصعب أحيانًا أن نوضّح ما الذي نعنيه بالبرمجيّات عالية الجودة. بالعودة إلى المبدأ OCP، يعود الفضل إلى برتراند ماير في وضع مصطلح مبدأ الفتح والإغلاق، حيث ظهر أوّل الأمر في كتابه البنية كائنيّة التوجّه للبرمجيّات "Object Oriented Software Construction" ينص هذا المبدأ على ما يلي: الذي يعنيه هذا المبدأ، هو أنّنا عندما نُصمّم جزءً من تطبيق برمجي، فإنّه من الضروري أن نضع في حسباننا إمكانيّة التوسّع المستقبليّ، فكلّنا يعلم أنّ المتطلّبات الخاصّة بالزبائن تتغيّر على الدوام وبسرعةٍ كبيرة. لذلك فإنّ الشيفرة البرمجيّة ستتغيّر وتتوسّع لتلبّي المزيد من المتطلّبات والمزايا، وقد لا يؤدّي هذا الأمر على الدوام إلى عواقب حميدة على الصعيد البرمجي. الهدف الذي يُنشده هذا المبدأ هو أن ننظر إلى المستقبل (ابنِ الآن، وخطّط للمستقبل) بحيث نصمّم تطبيقاتنا البرمجيّة بحيث لا تحتاج إلى تغيير في الشيفرة المكتوبة مسبقًا عند إضافة مزايا ووظائف جديدة إليها. لندع الشيفرة البرمجيّة تُعبّر عن نفسها مع المثال التالي: def area(geometric_entity): if geometric_entity.type() == SQUARE: return geometric_entity.a * geometric_entity.a elif geometric_entity.type() == CIRCLE: return PI * geometric_entity.r * geometric_entity.r else: raise UnknownEntityError("I literally have no idea.") قد توحي الشيفرة السابقة بالبساطة أوّل الأمر، ولكنّها تُظهر جانبًا أساسيًّا من مبدأ OCP. فإذا أردنا مثلًا أن تدعم الدالّة السابقة إمكانية حساب مساحة مستطيل فيمكن ذلك بسهولة وذلك بإضافة مقطع elif جديد. ولكن بالمتابعة على هذا المنوال، وفي حالة حساب مساحة شكل هندسي غير قياسي، فستتحول الأسطر البرمجيّة البسيطة السابقة إلى ما يزيد عن 1500 سطر برمجي لحساب مساحة هذا الشكل باستخدام تكامل ريمان Riemann Integral، مما سيجعل هذه الأسطر كوحش برمجيّ إذا لم يلتهمك، فإنّ مدير المشاريع سيفعل ذلك حتمًا! النقطة التي نريد الوصول إليها، أنّه في كلّ مرّة نريد فيها إحداث تغيير في البرنامج لدعم مزايا جديدة، فإنّه من الممكن أن يؤدّي هذا التغيير إلى مشاكل في عمل المزايا القديمة التي كانت تعمل بشكل جيّد أصلًا، وهذا أمر غير مرغوب بالطبع. وهذا ما يحذّرنا منه مبدأ OCP، فيجب أن تكون العناصر البرمجيّة مفتوحة للتوسعة (دعم مزايا إضافيّة) ولكنها مغلقة للتعديل (عدم الحاجة إلى تعديل الشيفرة التي تدعم المزايا القديمة). قد يتبادر إلى ذهن البعض أنّه في حالة حدوث مشاكل جرّاء هذا التعديل فمن الممكن إصلاحها باستخدام وحدات الاختبار unit tests ومنقّحات الأخطاء debuggers، ولكن لماذا نلجأ لمثل هذه الأساليب إذا كان بإمكاننا تجنّبها أصلًا؟ فدرهم وقاية خير من قنطار علاج. وكما أنّه من الصعب وضع تعريف رسميّ لمعيار الجودة للبرمجيّات، فكذلك الأمر بالنسبة لهذه المبادئ. فلا توجد قواعد صارمة للتقيّد بها، فكل شيء يعود للخبرة الشخصيّة والتخطيط الجيّد. ترجمة -وبتصرّف- للمقال Open/Closed Principle in Software Design لصاحبه Radek Pazdera.1 نقطة
-
مبدأ آخر من مبادئ التصميم الكائنيّ التوجّه ضمن مبادئ SOLID يُطلق عليه اسم مبدأ ليسكوف للاستبدال Liskov Substitution Principle ويُرمز له اختصارًا بالرمز LSP. سنبدأ هذا المبدأ بشيء من المفاهيم النظريّة. صاحبة هذا المبدأ هي البروفسور باربارا ليسكوف، وقد طرحته أوّل الأمر عام 1987 وكان ينص على ما يلي: قد يبدو الكلام السابق مبهمًا بعض الشيء، يمكننا توضيحه بالشكل التالي: "إذا استطعنا استبدال كل كائن O1 مكان كائن O2 فمن الممكن الجزم بأنّ S هو نوع فرعي (نوع ابن) للنوع T". ولكن في بعض الأحيان رغم أنّ S هو نوع فرعي للنوع T ولكن لا يمكن الاستبدال بين كائناتهما بالصورة الموضّحة قبل قليل وهذا بالطبع أمر غير جيّد. أعادت باربارا ليسكوف بالاشتراك مع جانيت وينغ Jeannette Wing صياغة المبدأ السابق بشكل مختصر أكثر في عام 1994 ليصبح على الشكل التالي: المقصود هنا أنّه إذا كانت خاصيّة أو دالّة (طريقة method) تعمل ضمن كائنات من النوع T، فينبغي أن تعمل أيضًا وبنفس الصورة ضمن كائنات من النوع S بحيث أنّ النوع S هو نوع ابن للنوع T. وهذا هو مبدأ ليسكوف للاستبدال الذي وصفه روبرت مارتن لاحقًا بصورة أكثر عمليّةً في إحدى مقالاته على الشكل التالي: بعد كلّ هذه المقدّمة النظريّة ثقيلة الظلّ بعض الشيء، ينبغي أن نُدعّم المفاهيم النظريّة السابقة ببعض الأمثلة التي توضّحها بالشكل المناسب. واحد من هذه الأمثلة التي تخرق هذا المبدأ هو تمثيل العلاقة بين المستطيل والمربّع بشكل كائنيّ. من البديهي تمامًا أن يكون لدينا صنف اسمه Square (مربّع) يكون صنفًا ابنًا للصنف Rectangle (مستطيل)، فمن الناحية الرياضيّة يُعتبر المربّع حالة خاصّة من المستطيل، فهو مستطيل تساوى فيه بعداه. لنعبّر في البداية عن الصنف Rectangle برمجيًّا بالشكل التالي: class Rectangle { int width; int height; public: int getWidth() { return width; } int getHeight() { return height; } virtual void setWidth(int value) { width = value; } virtual void setHeight(int value) { height = value; } }; وبما أنّ المربّع هو حالة خاصّة من المستطيل كما أسلفنا، فيمكن كتابة الصنف Square مع إعادة تعريف الطريقتين setWidth و setHeight: class Square : public Rectangle { public: void setWidth(int value) { width = value; height = value; } void setHeight(int value) { width = value; height = value; } }; سيضمن هذا التعديل على الطريقتين setWidth و setHeight ضمن الصنف Square أنّ أي كائن (مربّع) ننشئه من الصنف Square ستكون أضلاعه الأربعة متساوية الطول. لننظر الآن إلى الدّالة التالية التي سنستخدمها لتجريب البنية الكائنيّة السابقة: bool test(Rectangle &rectangle) { rectangle.setWidth(2); rectangle.setHeight(3); return rectangle.getWidth() * rectangle.getHeight() == 6; } تقبل الدّالة test تمرير كائن من النوع Rectangle أو كائن من النوع Square، وهذا جائز بالطبع لأنّ Square هو نوع ابن للنوع Rectangle. السؤال هنا هو ماذا سيحدث عند تمرير كائن من النوع Square إلى الدّالة test؟ ستُعيد الدّالة القيمة false رغم أنّ التقييم يجري على مرجع من النوع Rectangle (وسيط الدّالة). المشكلة هنا أنّه رغم أنّ المربّع هو مستطيل من الناحية الرياضيّة إلّا أنّه لا يتشارك السلوك نفسه معه. وهذا يُعتبر خرقًا واضحاً لمبدأ الاستبدال. فالكائنات من النوع Rectangle لا يمكن أن يتمّ استبدالها بكائنات من النوع Square رغم أنّ النوع Square هو نوع ابن للنوع Rectangle، لأنّ ذلك سيؤدّي إلى تغيّر في سلوك الطرائق الموجودة ضمن الصنف Rectangle كما هو واضح. لقد أوضح برتراند ماير هذه المسألة أيضًا على الشكل التالي: الإجراء من النص السابق قد يكون دالة أو طريقة method. الشروط البادئة هي الشروط التي يجب أن تتحقّق كي يتم استدعاء الطريقة وتنفيذها، أمّا الشروط اللّاحقة فهي محقّقة دومًا بعد انتهاء تنفيذ الطريقة. فالّذي قصده برتراند ماير هو أنّه عند إعادة كتابة تابع في صنف ابن يرث من صنف أب، يجب ألّا تكون الشروط البادئة أقوى من الشروط البادئة للطريقة الأصليّة (الموجودة في النوع الأب)، كما يجب ألّا تكون الشروط الّلاحقة أضعف من الشروط الّلاحقة للطريقة الأصليّة. في مسألتنا السابقة (مسألة المربّع والمستطيل)، لم تكن هناك أيّ شروط بادئة، ولكن كان هناك شرط لاحق للطريقة setHeight وهو أنّ هذه الطريقة يجب ألّا تُغيّر العرض width، وهذا الشرط تمّ خرقه (أصبح أضعف) عندما أعدنا تعريف الطريقة setHeight ضمن النوع Square. تُعتبر الوراثة في الحقيقة مفهومًا قويًّا ومحوريًّا في التصميم كائنيّ التوجّه، ولكن من السهل الوقوع في الأخطاء إذا لم نطبّق مبدأ ليسكوف للاستبدال، فقد تجد أنّ تصميمك الكائنيّ جيّد ومقنع، ولكن سرعان ما ستقع في المتاعب إذا لم تراعي هذا المبدأ. ترجمة -وبتصرّف- للمقال Liskov Substitution Principle لصاحبه Radek Pazdera.1 نقطة